2017-03-02 70 views
2

位置請看下面的表格和數據的SQL Server 2008數據庫:SQL Server 2008中 - 查找藝術品

CREATE TABLE sponsorships 
(
    sponsorshipID INT NOT NULL PRIMARY KEY IDENTITY, 
    sponsorshipLocationID INT NOT NULL, 
    sponsorshipArtworkID INT NOT NULL 
); 

INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (1, 1); 
INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (1, 2); 
INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (2, 1); 
INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (2, 2); 
INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (3, 3); 
INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (4, 3); 
INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (5, 4); 
INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (6, 1); 
INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (7, 1); 
INSERT INTO sponsorships (sponsorshipLocationID, sponsorshipArtworkID) 
VALUES (7, 3); 

SELECT * 
FROM sponsorships s 
ORDER BY s.sponsorshipLocationID, s.sponsorshipArtworkID 

我怎麼能生產出下面的輸出?

CREATE TABLE sponGroups 
(
    rank INT, 
    sponsorshipID INT, 
    sponsorshipLocationID INT, 
    sponsorshipArtworkID INT 
); 

INSERT INTO sponGroups VALUES (1, 1, 1, 1); 
INSERT INTO sponGroups VALUES (1, 2, 1, 2); 
INSERT INTO sponGroups VALUES (1, 3, 2, 1); 
INSERT INTO sponGroups VALUES (1, 4, 2, 2); 
INSERT INTO sponGroups VALUES (2, 5, 3, 3); 
INSERT INTO sponGroups VALUES (2, 6, 4, 3); 
INSERT INTO sponGroups VALUES (3, 7, 5, 4); 
INSERT INTO sponGroups VALUES (4, 8, 6, 1); 
INSERT INTO sponGroups VALUES (5, 9, 7, 1); 
INSERT INTO sponGroups VALUES (5, 10, 7, 3); 

SELECT * 
FROM sponGroups sg 
ORDER BY sg.rank, sg.sponsorshipID, sg.sponsorshipLocationID, sg.sponsorshipArtworkID 

小提琴可用,here

說明

圖形顯示在不同的位置。某些位置安裝了雙面圖稿(例如窗戶),以及一些單面(如牆壁)。例如,位置1的藝術品是雙面的 - 它具有贊助ArtworkIDs 1和2 - 並且位置5處有單面藝術品(贊助商ArtworkID 4)。

對於打印和安裝的目的,我需要一個查詢來產生每件作品,無論是單面還是兩面,以及所有與該作品有關的位置。 (參考上面提到的小提琴中的所需輸出)。例如,我需要告訴打印機:

  • 打印雙面圖稿(1,2)並將其安裝在位置(1,2 );
  • 打印單面圖稿(3)並將其安裝在位置(3,4);
  • 打印單面圖稿(4)並將其安裝在位置(5)處;
  • 打印單面圖稿(1)並將其安裝在位置(6);
  • 打印雙面圖稿(1,3)並將其安裝在位置(7)。

請注意,藝術有時會被重複使用,所以贊助ArtArtIDID1在單面和雙面位置都會使用。

我試圖使用DENSE_RANK(),一個遞歸CTE,並設置明智的鴻溝來解決這個問題,但還沒有能夠到目前爲止。先謝謝您的幫助。

+0

我已閱讀說明,但仍不知道「rank」列應代表什麼 – Lamak

+0

@SqlZim安裝了雙面圖稿的位置分配了兩件藝術品。例如。位置7分配了兩件藝術品,因此它是雙面位置。 – avejidah

+0

@Lamak「等級」欄是爲了說明我想要的分組;我解釋底部的項目符號列表直接對應於「等級」列。基本上我需要按照5個不同的請求順序將每個項目符號/等級發送給打印機/安裝程序。 – avejidah

回答

1

它可能看起來有點醜,但想法很簡單。

在第一組sponsorshipLocationID並建立一個逗號分隔的字符串與關聯的sponsorshipArtworkID列表。

然後根據此逗號分隔的藝術作品ID計算密集度。

在下面的查詢中,我使用FOR XML來連接字符串。這不是唯一的方法。有很好的CLR快速寫入功能。

我建議按照CTE逐步運行查詢,並檢查中間結果以瞭解它是如何工作的。

樣本數據

DECLARE @sponsorships TABLE 
(
    sponsorshipID INT NOT NULL PRIMARY KEY IDENTITY, 
    sponsorshipLocationID INT NOT NULL, 
    sponsorshipArtworkID INT NOT NULL 
); 

INSERT INTO @sponsorships (sponsorshipLocationID, sponsorshipArtworkID) VALUES 
(1, 1), 
(1, 2), 
(2, 1), 
(2, 2), 
(3, 3), 
(4, 3), 
(5, 4), 
(6, 1), 
(7, 1), 
(7, 3); 

查詢

WITH 
CTE_Locations 
AS 
(
    SELECT 
     sponsorshipLocationID 
    FROM 
     @sponsorships AS S 
    GROUP BY 
     sponsorshipLocationID 
) 
,CTE_Artworks 
AS 
(
    SELECT 
     CTE_Locations.sponsorshipLocationID 
     ,CA_Data.Artwork_Value 
    FROM 
     CTE_Locations 
     CROSS APPLY 
     (
      SELECT CAST(S.sponsorshipArtworkID AS varchar(10)) + ',' 
      FROM 
       @sponsorships AS S 
      WHERE 
       S.sponsorshipLocationID = CTE_Locations.sponsorshipLocationID 
      ORDER BY 
       S.sponsorshipArtworkID 
      FOR XML PATH(''), TYPE 
     ) AS CA_XML(XML_Value) 
     CROSS APPLY 
     (
      SELECT CA_XML.XML_Value.value('.', 'NVARCHAR(MAX)') 
     ) AS CA_Data(Artwork_Value) 
) 
,CTE_Rank 
AS 
(
    SELECT 
     sponsorshipLocationID 
     ,Artwork_Value 
     ,DENSE_RANK() OVER (ORDER BY Artwork_Value) AS r 
    FROM CTE_Artworks 
) 
SELECT 
    CTE_Rank.r 
    ,S.sponsorshipID 
    ,CTE_Rank.sponsorshipLocationID 
    ,S.sponsorshipArtworkID 
FROM 
    CTE_Rank 
    INNER JOIN @sponsorships AS S 
     ON S.sponsorshipLocationID = CTE_Rank.sponsorshipLocationID 
ORDER BY 
    S.sponsorshipID 
; 

結果

+---+---------------+-----------------------+----------------------+ 
| r | sponsorshipID | sponsorshipLocationID | sponsorshipArtworkID | 
+---+---------------+-----------------------+----------------------+ 
| 2 |    1 |      1 |     1 | 
| 2 |    2 |      1 |     2 | 
| 2 |    3 |      2 |     1 | 
| 2 |    4 |      2 |     2 | 
| 4 |    5 |      3 |     3 | 
| 4 |    6 |      4 |     3 | 
| 5 |    7 |      5 |     4 | 
| 1 |    8 |      6 |     1 | 
| 3 |    9 |      7 |     1 | 
| 3 |   10 |      7 |     3 | 
+---+---------------+-----------------------+----------------------+ 

秩的實際值與您預期的結果不完全相同,但它們可以正確地對行進行分組。

+0

謝謝弗拉基米爾,這確實實現了目標。看起來這應該是純粹的set-wise可行的(沒有連接,那就是),但是這比我想出的任何東西都要好。我很感激幫助。 – avejidah

+0

@avejidah,有一個類似的[問題](http://stackoverflow.com/q/30680266/4116017)和解決方案類似於我的答案在這裏的答案。我用'CHECKSUM_AGG'顯示了一個近似的解決方案。 –