有一个名为PRODUCT_PRICE的表格:
CREATE TABLE [TEST].[PRODUCT_PRICE]
(
[PRICE_ID] [bigint] NOT NULL,
[PRODUCT_ID] [bigint] NOT NULL,
[PRICE_DATE] [date] NOT NULL,
[IS_SALE_PRICE] [bit] NOT NULL,
[UNIT_PRICE] [decimal](18, 2) NOT NULL
)
它有以下记录:
PRICE_ID PRODUCT_ID PRICE_DATE IS_SALE_PRICE UNIT_PRICE
-------- ---------- ---------- ------------- ----------
1 15 2015-05-12 False 0,05
2 15 2015-05-12 True 0,04
3 25 2015-05-12 False 1,45
4 35 2015-05-12 True 2,65
编辑:只能有两种价格 - 购买价格和促销价格。不能有3行或更多行具有相同的PRODUCT_ID
和PRICE_DATE
。
我想写一个SELECT
语句,结果如下:
PRICE_ID PRODUCT_ID PRICE_DATE IS_SALE_PRICE UNIT_PRICE PRICE_ID_2 IS_SALE_PRICE_2 UNIT_PRICE_2
-------- ---------- ---------- ------------- ---------- ---------- --------------- ------------
1 15 2015-05-12 False 0,05 2 True 0,04
3 25 2015-05-12 False 1,45 NULL NULL NULL
4 35 2015-05-12 True 2,65 NULL NULL NULL
我尝试了FULL OUTER JOIN
,但它产生了4行而不是3行,这是正确的,但不是我想要的:
SELECT
PR1.*,
PR2.PRICE_ID AS PRICE_ID_2,
PR2.IS_SALE_PRICE AS IS_SALE_PRICE_2,
PR2.UNIT_PRICE AS UNIT_PRICE_2
FROM PRODUCT_PRICE AS PR1
FULL OUTER JOIN PRODUCT_PRICE AS PR2
ON PR1.PRODUCT_ID = PR2.PRODUCT_ID
AND PR1.PRICE_DATE = PR2.PRICE_DATE
AND PR1.PRICE_ID <> PR2.PRICE_ID
AND PR1.IS_SALE_PRICE <> PR2.IS_SALE_PRICE
WHERE
PR1.PRICE_DATE = '20150512'
ORDER BY PR1.PRICE_ID
以上查询的结果:
| PRICE_ID | PRODUCT_ID | PRICE_DATE | IS_SALE_PRICE | UNIT_PRICE | PRICE_ID_2 | IS_SALE_PRICE_2 | UNIT_PRICE_2 |
|----------|------------|------------|---------------|------------|------------|-----------------|--------------|
| 1 | 15 | 2015-05-12 | false | 0.05 | 2 | true | 0.04 |
| 2 | 15 | 2015-05-12 | true | 0.04 | 1 | false | 0.05 |
| 3 | 25 | 2015-05-12 | false | 1.45 | (null) | (null) | (null) |
| 4 | 35 | 2015-05-12 | true | 2.65 | (null) | (null) | (null) |
基本上我想JOIN
一个自己的表并删除重复项。
注意:PRICE_ID
是identity
字段(主键)。但自然键是PRODUCT_ID
,PRICE_DATE
对。我想为每个唯一PRODUCT_ID
和PRICE_DATE
添加一行。
答案 0 :(得分:3)
如果您确定每个PRODUCT_ID
- PRICE_DATE
组合最多只有2行,则可以使用条件聚合而不是JOIN
:
SELECT
PRICE_ID = MAX(CASE WHEN RN = 1 THEN PRICE_ID END),
PRODUCT_ID,
PRICE_DATE,
IS_SALE_PRICE = MAX(CASE WHEN RN = 1 THEN CAST(IS_SALE_PRICE AS INT) END),
UNIT_PRICE = MAX(CASE WHEN RN = 1 THEN UNIT_PRICE END),
PRICE_ID2 = MAX(CASE WHEN RN = 2 THEN PRICE_ID END),
IS_SALE_PRICE2 = MAX(CASE WHEN RN = 2 THEN CAST(IS_SALE_PRICE AS INT) END),
UNIT_PRICE2 = MAX(CASE WHEN RN = 2 THEN UNIT_PRICE END)
FROM (
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY PRODUCT_ID, PRICE_DATE ORDER BY IS_SALE_PRICE)
FROM PRODUCT_PRICE
)t
GROUP BY PRODUCT_ID, PRICE_DATE
ORDER BY PRODUCT_ID, PRICE_DATE
<强>结果强>
| PRICE_ID | PRODUCT_ID | PRICE_DATE | IS_SALE_PRICE | UNIT_PRICE | PRICE_ID2 | IS_SALE_PRICE2 | UNIT_PRICE2 |
|----------|------------|------------|---------------|------------|-----------|----------------|-------------|
| 1 | 15 | 2015-05-12 | 0 | 0.05 | 2 | 1 | 0.04 |
| 3 | 25 | 2015-05-12 | 0 | 1.45 | (null) | (null) | (null) |
| 4 | 35 | 2015-05-12 | 1 | 2.65 | (null) | (null) | (null) |
如果您坚持使用JOIN
,则可以使用FULL JOIN
:
SELECT
PRICE_ID = CASE WHEN PP.PRICE_ID IS NOT NULL THEN PP.PRICE_ID ELSE SP.PRICE_ID END,
PRODUCT_ID = CASE WHEN PP.PRICE_ID IS NOT NULL THEN PP.PRODUCT_ID ELSE SP.PRODUCT_ID END,
PRICE_DATE = CASE WHEN PP.PRICE_ID IS NOT NULL THEN PP.PRICE_DATE ELSE SP.PRICE_DATE END,
IS_SALE_PRICE = CASE WHEN PP.PRICE_ID IS NOT NULL THEN PP.IS_SALE_PRICE ELSE SP.IS_SALE_PRICE END,
UNIT_PRICE = CASE WHEN PP.PRICE_ID IS NOT NULL THEN PP.UNIT_PRICE ELSE SP.UNIT_PRICE END,
PRICE_ID2 = CASE WHEN PP.PRICE_ID IS NOT NULL THEN SP.PRICE_ID END,
IS_SALE_PRICE2 = CASE WHEN PP.PRICE_ID IS NOT NULL THEN SP.IS_SALE_PRICE END,
UNIT_PRICE2 = CASE WHEN PP.PRICE_ID IS NOT NULL THEN SP.UNIT_PRICE END
FROM (
SELECT *
FROM PRODUCT_PRICE
WHERE IS_SALE_PRICE = 0
)AS PP
FULL JOIN(
SELECT *
FROM PRODUCT_PRICE
WHERE IS_SALE_PRICE = 1
)AS SP
ON PP.PRODUCT_ID = SP.PRODUCT_ID
AND PP.PRICE_DATE = SP.PRICE_DATE
ORDER BY PRODUCT_ID, PRICE_DATE
答案 1 :(得分:0)
您获得PRICE_ID=1
vs PRICE_ID =2
和PRICE_ID=2
vs PRICE_ID=1
所以你有一个重复的行。
在ON CLAUSE
中,join
PRICE_ID1 < PRICE_ID2
将此添加到ON CLAUSE:
AND PR1.PRICE_ID < PR2.PRICE_ID
并使用LEFT JOIN
随着这些变化,你将获得4行,你还需要避免第2行,因为它已经在行“内部”了。所以你只需要在where子句中过滤寄存器:
AND PR1.PRICE_ID in (select min(PRICE_ID) from PRODUCT_PRICE group by PRODUCT_ID)
答案 2 :(得分:0)
执行FULL OUTER JOIN
。
select ...
from PRODUCT_PRICE p1
FULL OUTER JOIN PRODUCT_PRICE p2
ON p1.PRODUCT_ID = p2.PRODUCT_ID
AND p1.PRICE_DATE = p2.PRICE_DATE
AND p1.IS_SALE_PRICE = 'true
AND p2.IS_SALE_PRICE = 'false'
编写选择列表列。并调整IS_SALE_PRICE比较。
替代解决方案,派生表FULL OUTER JOIN
:
select ...
from (select * from PRODUCT_PRICE
where IS_SALE_PRICE = 'true') as p1
FULL OUTER JOIN
(select * from PRODUCT_PRICE
where IS_SALE_PRICE = 'false') as p2
ON p1.PRODUCT_ID = p2.PRODUCT_ID
AND p1.PRICE_DATE = p2.PRICE_DATE