Sql-Server
如何避免在一系列嵌套的 SELECT 語句中重複資訊?
我正在研究一個 SQL 查詢,該查詢根據過去的購買記錄匯總客戶歷史記錄(行業是場地票務)。該報告將很大,大約有 80-90 列,在輸出 CSV 中每個事件或每個記錄的事件類別為一列。
數據庫結構要求我使用嵌套的選擇語句將必要的數據放入每條記錄的列中——每列包含該類型事件的票數。我在理論上知道如何做到這一點,但是每個嵌入的 select 語句都非常大,以至於完整的報告會突破我的數據庫界面上 8,000 個字元的限制。其中一個語句如下所示:
(select count (*) FROM guest ig, event2 e, eventseat es, "order" o WHERE ig.guestid = g.guestid and ig.guestid = o.guestid and o.orderid = es.orderid and e.eventid = es.eventid and e.incometype = 'T' and e.eventtype in ('SS', 'BMF') and es.status in ('2','4') and es.price <> '0.00' and es.price <> '5.00' and e.year = '2010' <-- THESE LINES ARE THE ONLY ONES THAT and e.run in ('SS-DANCE') <-- CHANGE PER SELECT STATEMENT ) as 'SS-Dance',
這大約是 400 個字元,僅在單個查詢中為 <20 次迭代留下足夠的空間,而不會超過字元限制。
有沒有辦法減少或概括它,以便我不需要在每個 SELECT 中的重複資訊上浪費所有這些字元?
我在以下連結中匯總了一個範例,其中包含我的數據庫結構的簡化版本和一些範例數據。目標是在每個嵌套 SELECT 不使用這麼多字元的情況下獲得相同的結果數據。
;WITH x AS ( SELECT g.guestid, e.[year], e.run, c = COUNT(*) FROM dbo.guest AS g INNER JOIN dbo.[order] AS o ON g.guestid = o.guestid INNER JOIN dbo.eventseat AS es ON o.orderid = es.orderid INNER JOIN dbo.event2 AS e ON e.eventid = es.eventid WHERE e.incometype = 'T' AND e.eventtype in ('SS', 'BMF') AND es.status in ('2','4') AND es.price NOT IN ( '0.00', '5.00') AND e.[year] = '2010' AND e.run IN ('SS-DANCE', 'SS-FILM', 'SS-OPERA') GROUP BY g.guestid, e.[Year], e.run ), y AS ( SELECT * FROM x PIVOT (MAX(c) FOR run IN ([SS-DANCE],[SS-FILM],[SS-OPERA])) AS z ) SELECT y.guestid, y.[year], g.[first], g.[last], [SS-DANCE] = COALESCE(y.[SS-DANCE], 0), [SS-FILM] = COALESCE(y.[SS-FILM], 0), [SS-OPERA] = COALESCE(y.[SS-OPERA], 0) FROM y INNER JOIN dbo.guest AS g ON y.guestid = g.guestid;
我不確定我的 where 子句是否對你有用。目前假設您只關心這三種類型(舞蹈、電影和歌劇)並且您只關心 2010 年。如果您需要跨年,您可以刪除該
WHERE
子句。如果您只關心 2010 年的舞蹈和任何一年的電影,您將需要編寫一組更複雜的 where 子句。一些評論:
- 盡量避免保留字,如
order
,和. 這些只會使事情複雜化,因為它們需要用方括號括起來(這比大多數情況下的可讀性和明確性更可取)。year``first``last``"double quotes"
- 總是使用
dbo.
(或任何schema
合適的前綴)。- 正如我上面建議的那樣,堅持使用顯式
INNER JOIN
語法。FROM x, y, z
是給鳥兒的。