[英]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.