![](/img/trans.png)
[英]SQL Server - Joining two tables directly or, sometimes, through a third table
[英]Generating a derived table in SSRS from last purchases in two different SQL Server tables, and then joining with a third
假設我有三個表:
CUST_ID
)的客戶信息之一 CUST_ID, PANT_TYPE, PANT_DATE
) CUST_ID, SHIRT_TYPE, SHIRT_DATE
) 另外,我希望排除某些褲子類型和某些襯衫類型(PANT_TYPE不是'JEANS',SHIRT_TYPE不是'TUXEDO'),並且僅獲取最近購買的褲子和襯衫。
因此,理想情況下,我將最終得到如下最終表:
CUST_ID, LAST_PANT_TYPE, LAST_PANT_DATE, LAST_SHIRT_TYPE, LAST_SHIRT_DATE
在工作了四個小時之后,我試圖使該解決方案生效,但是'OVER'語句中斷了SSRS並導致測試查詢時出現問題,甚至有時會隨機刪除該字段。 因此,我認為某種派生表可能有效。
我對SQL還是很陌生,已經學到了很多解決這個問題的方法,但是我需要到達STAT。
您可以嘗試使用APPLY
運算符,例如:
SELECT
C.CUST_ID
, PANT.PANT_TYPE LAST_PANT_TYPE
, PANT.PANT_DATE LAST_PANT_DATE
, SHIRT.SHIRT_TYPE LAST_SHIRT_TYPE
, SHIRT.SHIRT_DATE LAST_SHIRT_DATE
FROM
CUSTOMER C
OUTER APPLY
(
SELECT TOP 1
P.PANT_TYPE
, P.PANT_DATE
FROM PANT P
WHERE
P.CUST_ID = C.CUST_ID
AND P.PANT_TYPE <> 'JEANS'
ORDER BY P.PANT_DATE DESC
) PANT
OUTER APPLY
(
SELECT TOP 1
S.SHIRT_TYPE
, S.SHIRT_DATE
FROM SHIRT S
WHERE
S.CUST_ID = C.CUST_ID
AND S.SHIRT_TYPE <> 'TUXEDO'
ORDER BY S.SHIRT_DATE DESC
) SHIRT
使用OUTER APPLY
(與CROSS APPLY
相對)可確保不會過濾掉任何客戶(如果在各自的表中沒有針對客戶的數據,則將在“ PANT”或“ SHIRT”列中返回NULL
)。
對派生表使用通用表表達式 ,查詢看起來像這樣:
WITH
p (cust_id, pant_type, pant_date, rn) AS (
SELECT cust_id, pant_type, pant_date,
ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY pant_date DESC)
FROM Pants WHERE pant_type NOT IN ('JEANS')
),
s (cust_id, shirt_type, shirt_date, rn) AS (
SELECT cust_id, shirt_type, shirt_date,
ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY shirt_date DESC)
FROM Shirts WHERE shirt_type NOT IN ('TUXEDO')
)
SELECT c.cust_id,
p.pant_type AS last_pant_type, p.pant_date AS last_pant_date,
s.shirt_type AS last_shirt_type, s.shirt_date AS last_shirt_date
FROM Customers c
LEFT JOIN p ON c.cust_id = p.cust_id AND p.rn = 1
LEFT JOIN s ON c.cust_id = s.cust_id AND s.rn = 1;
我最終制作了數據,並使用ROW_NUMBER標識了上一次購買。
SELECT 1 AS CUST_ID
INTO #CUSTOMERS
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
SELECT 1 AS CUST_ID, 'SLACKS' AS PANT_TYPE, CAST('1/1/2017' AS DATE) AS PANT_DATE
INTO #PANTS
UNION
SELECT 1, 'CARGO SHORTS', CAST('2/2/2018' AS DATE)
UNION
SELECT 1, 'SLACKS', CAST('3/3/2018' AS DATE)
UNION
SELECT 2, 'CARGO PANTS', CAST('2/2/2017' AS DATE)
UNION
SELECT 2, 'SLACKS', CAST('4/4/2018' AS DATE)
UNION
SELECT 3, 'CARGO PANTS', CAST('4/1/2018' AS DATE)
UNION
SELECT 3, 'SLACKS', CAST('5/8/2017' AS DATE)
UNION
SELECT 4, 'CARGO SHORTS', CAST('2/2/2018' AS DATE)
UNION
SELECT 4, 'SLACKS', CAST('3/3/2018' AS DATE)
UNION
SELECT 4, 'CARGO PANTS', CAST('2/2/2017' AS DATE)
UNION
SELECT 4, 'SLACKS', CAST('4/4/2018' AS DATE)
UNION
SELECT 4, 'CARGO PANTS', CAST('4/1/2018' AS DATE)
UNION
SELECT 4, 'SLACKS', CAST('5/8/2017' AS DATE)
SELECT 1 AS CUST_ID, 'POLO' AS SHIRT_TYPE, CAST('1/1/2017' AS DATE) AS SHIRT_DATE
INTO #SHIRTS
UNION
SELECT 1, 'POLO - LONG SLEEVE', CAST('2/2/2018' AS DATE)
UNION
SELECT 1, 'POLO - LONG SLEEVE', CAST('3/3/2018' AS DATE)
UNION
SELECT 2, 'POLO', CAST('2/2/2017' AS DATE)
UNION
SELECT 2, 'POLO - LONG SLEEVE', CAST('4/4/2018' AS DATE)
UNION
SELECT 3, 'T-SHIRT', CAST('4/1/2018' AS DATE)
UNION
SELECT 3, 'POLO', CAST('5/8/2017' AS DATE)
UNION
SELECT 4, 'T-SHIRT', CAST('2/2/2018' AS DATE)
UNION
SELECT 4, 'POLO', CAST('3/3/2018' AS DATE)
UNION
SELECT 4, 'T-SHIRT', CAST('2/2/2017' AS DATE)
UNION
SELECT 4, 'POLO - LONG SLEEVE', CAST('4/4/2018' AS DATE)
UNION
SELECT 4, 'T-SHIRT', CAST('4/1/2018' AS DATE)
UNION
SELECT 4, 'POLO', CAST('5/8/2017' AS DATE)
SELECT C.CUST_ID, P.PANT_TYPE, P.PANT_DATE,
S.SHIRT_TYPE, S.SHIRT_DATE
FROM #CUSTOMERS C
LEFT JOIN (SELECT CUST_ID, PANT_TYPE, PANT_DATE, ROW_NUMBER()OVER(PARTITION BY CUST_ID ORDER BY PANT_DATE DESC) AS ROW_NUM FROM #PANTS) P ON P.CUST_ID = C.CUST_ID AND P.ROW_NUM = 1
LEFT JOIN (SELECT CUST_ID, SHIRT_TYPE, SHIRT_DATE, ROW_NUMBER()OVER(PARTITION BY CUST_ID ORDER BY SHIRT_DATE DESC) AS ROW_NUM FROM #SHIRTS) S ON S.CUST_ID = C.CUST_ID AND S.ROW_NUM = 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.