2009-12-16 35 views
7

Tôi đã dành một vài ngày làm việc về điều này và đang đi vòng vòng.Cú pháp SQL để Xoay nhiều bảng

Câu hỏi của tôi là dựa trên câu trả lời tôi chấp nhận trong bài viết này: stackoverflow question

bây giờ tôi đã chuyển dữ liệu của tôi từ một bảng 400 cột duy nhất để một cấu trúc cơ sở dữ liệu nhiều dễ quản lý hơn với nhiều nhờ Damir Sudarevic.

cơ sở dữ liệu của tôi trông như thế này:

alt text

CREATE TABLE JobFiles (
    JobID UNIQUEIDENTIFIER PRIMARY KEY, 
    MachineID UNIQUEIDENTIFIER REFERENCES Machines(MachineID), 
    [Desc] NVARCHAR(MAX), 
    Name NVARCHAR(255), 
    JobOpen BIT, 
    [CreateDate] DATETIME NOT NULL DEFAULT GETDATE(), 
    [ModifyDate] DATETIME NOT NULL DEFAULT GETDATE(), 
    [CreatedByUser] NVARCHAR(64) DEFAULT '', 
    [ModifiedByUser] NVARCHAR(64) DEFAULT '') 
GO 

CREATE TABLE JobParamType (
    ParamTypeID UNIQUEIDENTIFIER PRIMARY KEY, 
    Name NVARCHAR(255), 
    [Desc] NVARCHAR(MAX), 
    IsTrait NVARCHAR) 

GO 
CREATE TABLE JobParamGroup (
    ParamGroupID UNIQUEIDENTIFIER PRIMARY KEY, 
    Name NVARCHAR(255), 
    [Desc] NVARCHAR(MAX)) 

GO 


CREATE TABLE JobParams (
    ParamID UNIQUEIDENTIFIER PRIMARY KEY, 
    ParamTypeID UNIQUEIDENTIFIER REFERENCES JobParamType(ParamTypeID), 
    ParamGroupID UNIQUEIDENTIFIER REFERENCES JobParamGroup(ParamGroupID), 
    JobFileID UNIQUEIDENTIFIER REFERENCES JobFiles(JobID), 
    IsEnabled BIT) 

GO 

-- Text based property 
CREATE TABLE JobTrait (
    ParamID UNIQUEIDENTIFIER PRIMARY KEY REFERENCES JobParams(ParamID), 
    Value NVARCHAR(MAX)) 
GO 

-- Numeric based property 
CREATE TABLE JobMeasurement (
    ParamID UNIQUEIDENTIFIER PRIMARY KEY REFERENCES JobParams(ParamID), 
    Value FLOAT, 
    Format NVARCHAR(20), 
    Unit NVARCHAR(MAX)) 
GO 

Tuy nhiên, đối với một chức năng cụ thể của ứng dụng của tôi, tôi cần phải liệt kê tất cả các hàng JobParamType.Name như cột chứa một JobMeasurement.Value hoặc JobTrait. Giá trị như dữ liệu của nó cho mỗi JobFiles.Name.

JobParamType.IsTrait được sử dụng để xác định xem giá trị có phải là Đo lường hoặc Trait hay không.

tức

JobName | ParamName1  | ParamName2  | ParamName3  ... | ParamName400 
"MyJob"  MesurementValue TraitValue   MesurementValue ... TraitValue 
"TestJob" MesurementValue TraitValue   MesurementValue ... TraitValue 
"Job2"  MesurementValue TraitValue   MesurementValue ... TraitValue 

etc 

Tôi đã được chơi với các bảng pivoting và đã quản lý để có được các cột từ bảng JobParamType bằng cách nhìn vào các ví dụ và sau đó nhưng nó bây giờ là nhận được khá phức tạp bởi vì dữ liệu của tôi được chia giữa một số bảng và nó đang bắt đầu làm cho đầu của tôi bị tổn thương !!!

DECLARE @cols NVARCHAR(MAX) 
SELECT @cols = STUFF((SELECT DISTINCT TOP 10 PERCENT 
           '],[' + tParams.Name 
         FROM dbo.JobParamType AS tParams 
         ORDER BY '],[' + tParams.Name 
         FOR XML PATH('') 
        ), 1, 2, '') + ']' 
print @cols 

Tôi hy vọng ai đó có thể giúp tôi với việc xoay vòng và nhận dữ liệu từ nhiều bảng.

Tôi hy vọng điều này có ý nghĩa và tôi mong được sự giúp đỡ và thảo luận của bạn.

Cảm ơn bạn đã nâng cao.

Trả lời

8

Tôi sẽ đăng một vài ví dụ từ this model - bởi vì tôi đã có chúng. Cả hai mô hình đều rất giống nhau, vì vậy bạn không nên gặp quá nhiều rắc rối khi áp dụng kỹ thuật này.

Khi nói đến đau đầu, tôi thấy rằng cách đơn giản nhất là đi từng bước và tối ưu hóa sau.

Bước 1.
Tạo chế độ xem để làm phẳng mô hình; (see the model)

CREATE VIEW dbo.vProperties AS 
SELECT m.MachineID AS [Machine ID] 
,s.SetupID AS [Setup ID] 
,p.PropertyID AS [Property ID] 
,t.PropertyTypeID AS [Property Type ID] 
,m.Name AS [Machine Name] 
,s.Name AS [Setup Name] 
,t.Name AS [Property Type Name] 
,t.IsTrait AS [Is Trait] 
,x.Value AS [Measurement Value] 
,x.Unit AS [Unit] 
,y.Value AS [Trait] 
FROM dbo.Machine AS m 
JOIN dbo.Setup AS s ON s.MachineID = m.MachineID 
JOIN dbo.Property AS p ON p.SetupID = s.SetupID 
JOIN dbo.PropertyType AS t ON t.PropertyTypeID = p.PropertyTypeID 
LEFT JOIN dbo.Measurement AS x ON x.PropertyID = p.PropertyID 
LEFT JOIN dbo.Trait AS y ON y.PropertyID = p.PropertyID 

Bước 2.

Tạo chế độ xem chỉ tạo [Setup Name], [Property Type Name], [Value]; lưu ý rằng trong giá trị đo lường này và đặc điểm kết thúc trong cùng một cột. Bạn có lẽ sẽ sử dụng JobName, ParameterTypeName, Value

CREATE VIEW dbo.vSetupValues AS 
SELECT [Setup Name] 
     ,[Property Type Name] 
     ,COALESCE(cast([Measurement Value] AS varchar(50)), [Trait]) AS [Val] 
FROM dbo.vProperties 

Bước 3.

Tạo danh sách các tài sản (thông số) với một cột để đặt hàng bởi

DECLARE @Props TABLE (
id int IDENTITY (1,1) 
,PropName varchar(50) 
); 

INSERT INTO @Props (PropName) 
SELECT DISTINCT [Name] 
FROM dbo.PropertyType 

Bước 4.

Bây giờ tôi tự động sẽ tạo ra nội dung truy vấn

DECLARE @qw TABLE(
id int IDENTITY (1,1) 
, txt nchar(500) 
) 

INSERT INTO @qw (txt) 
    SELECT 'SELECT' UNION 
    SELECT '[Setup Name]' ; 

INSERT INTO @qw (txt) 
    SELECT ',MAX(CASE [Property Type Name] WHEN ''' + PropName 
    + ''' THEN Val ELSE NULL END) AS [' + PropName + ']' 
    FROM @Props 
    ORDER BY id; 

INSERT INTO @qw (txt) 
SELECT 'FROM dbo.vSetupValues' UNION 
SELECT 'GROUP BY [Setup Name]' UNION 
SELECT 'ORDER BY [Setup Name]'; 

Bước 5.

Và đây là văn bản của truy vấn, hình thành điểm này tôi có thể gói này vào một thủ tục được lưu trữ, dạng xem khác hoặc vào biến để sử dụng làm sql động.

SELECT txt FROM @qw 

lợi nhuận

SELECT                                                                                                                            
[Setup Name]                                                                                                                           
,MAX(CASE [Property Type Name] WHEN 'Diameter LSL' THEN [Val] ELSE NULL END) AS [Diameter LSL]                                                                                                      
,MAX(CASE [Property Type Name] WHEN 'Diameter USL' THEN [Val] ELSE NULL END) AS [Diameter USL]                                                                                                      
,MAX(CASE [Property Type Name] WHEN 'Force LSL' THEN [Val] ELSE NULL END) AS [Force LSL]                                                                                                        
,MAX(CASE [Property Type Name] WHEN 'Force USL' THEN [Val] ELSE NULL END) AS [Force USL]                                                                                                        
,MAX(CASE [Property Type Name] WHEN 'Leak LSL' THEN [Val] ELSE NULL END) AS [Leak LSL]                                                                                                        
,MAX(CASE [Property Type Name] WHEN 'Leak USL' THEN [Val] ELSE NULL END) AS [Leak USL]                                                                                                        
,MAX(CASE [Property Type Name] WHEN 'Press Travel LSL' THEN [Val] ELSE NULL END) AS [Press Travel LSL]                                                                                                    
,MAX(CASE [Property Type Name] WHEN 'Press Travel USL' THEN [Val] ELSE NULL END) AS [Press Travel USL]                                                                                                    
,MAX(CASE [Property Type Name] WHEN 'Seal Height LSL' THEN [Val] ELSE NULL END) AS [Seal Height LSL]                                                                                                     
,MAX(CASE [Property Type Name] WHEN 'Seal Height USL' THEN [Val] ELSE NULL END) AS [Seal Height USL]                                                                                                     
FROM dbo.vSetupValues                                                                                                                        
GROUP BY [Setup Name]                                                                                                                        
ORDER BY [Setup Name]          

Và nếu tôi chạy này:
alt text http://www.damirsystems.com/dp_images/machinesetup_results.png


CẬP NHẬT: lỗi cố định ở bước 4, đã mất tích max() và thêm kết quả ví dụ.

+0

Cảm ơn bạn ... thời gian và nỗ lực của bạn được đánh giá rất cao. Bit phức tạp hơn tôi đầu tiên mặc dù nhiệm vụ này sẽ được như vậy sẽ được sàng lọc thông qua ví dụ của bạn ngày hôm nay và sẽ phá vỡ nó thành các bước. – Belliez

+0

Damir, một thiên tài của bạn, cảm ơn bạn. Điều đó hoạt động hoàn hảo. Chỉ một câu hỏi cuối cùng. Làm thế nào tôi sẽ chạy lệnh này như bạn có ở trên. Bước 5 "SELECT txt FROM @qw" hiển thị lệnh trong một bảng (thông qua SQL Management Studio) và tôi phải sao chép và dán nó vào một truy vấn mới. Một lần nữa, cảm ơn bạn – Belliez

+0

Ý tưởng là "đóng gói" truy vấn cuối cùng vào chế độ xem, thủ tục hoặc biến - tùy thuộc vào tần suất danh sách các thông số của bạn có thể thay đổi. Nếu 400 tham số đó thay đổi vài lần trong một năm, hãy sử dụng chế độ xem và tạo các thay đổi theo cách thủ công. Nếu họ thay đổi hàng ngày, hãy đặt biến này thành biến và thực thi như sql động - cũng tự động thực hiện bước 3 và 4. –

Các vấn đề liên quan