选择具有唯一元素的对

时间:2017-11-16 17:18:27

标签: sql amazon-redshift

我有一个这种形式的潜在匹配列表:

rev_id, click_id
A,   1
A,   2
B,   1
B,   2
B,   3
C,   3

如何选择具有唯一元素的对,以便两列中的值只显示一次?结果如下:

rev_id, click_id
A,   1
B,   2
C,   3

是否有一个窗口功能可以让我得到我想要的东西?

select rev_id, ???? 
from matches
group by 1

1 个答案:

答案 0 :(得分:1)

因此,在您的评论中,您的要求是,一旦变得更加困难,您只能使用click_id。但是因为你使用3个rev_ids,你可以使用3个笛卡尔连接,然后缩小到允许的选项,然后选择1并格式化你想要的方式。不幸的是,这种类型的答案不具备可扩展性。

;WITH cteOption AS (
    SELECT TOP 1 *
    FROM
       (
          SELECT DISTINCT
             CASE
                WHEN m1.rev_id < m2.rev_id AND m1.rev_id < m3.rev_id THEN m1.rev_id
                WHEN m2.rev_id < m1.rev_id AND m2.rev_id < m3.rev_id THEN m2.rev_id
                ELSE m3.rev_id
             END as rev1
             ,CASE
                WHEN m1.rev_id < m2.rev_id AND m1.rev_id < m3.rev_id THEN m1.click_id
                WHEN m2.rev_id < m1.rev_id AND m2.rev_id < m3.rev_id THEN m2.click_id
                ELSE m3.click_id
             END as click1
             ,CASE
                WHEN m1.rev_id > m2.rev_id AND m1.rev_id < m3.rev_id THEN m1.rev_id
                WHEN m1.rev_id > m3.rev_id AND m1.rev_id < m2.rev_id THEN m1.rev_id
                WHEN m2.rev_id > m1.rev_id AND m2.rev_id < m3.rev_id THEN m2.rev_id
                WHEN m2.rev_id > m3.rev_id AND m2.rev_id < m1.rev_id THEN m2.rev_id
                ELSE m3.rev_id
             END as rev2
             ,CASE
                WHEN m1.rev_id > m2.rev_id AND m1.rev_id < m3.rev_id THEN m1.click_id
                WHEN m1.rev_id > m3.rev_id AND m1.rev_id < m2.rev_id THEN m1.click_id
                WHEN m2.rev_id > m1.rev_id AND m2.rev_id < m3.rev_id THEN m2.click_id
                WHEN m2.rev_id > m3.rev_id AND m2.rev_id < m1.rev_id THEN m2.click_id
                ELSE m3.click_id
             END as click2
             ,CASE
                WHEN m1.rev_id > m2.rev_id AND m1.rev_id > m3.rev_id THEN m1.rev_id
                WHEN m2.rev_id > m1.rev_id AND m2.rev_id > m3.rev_id THEN m2.rev_id
                ELSE m3.rev_id
             END as rev3
             ,CASE
                WHEN m1.rev_id > m2.rev_id AND m1.rev_id > m3.rev_id THEN m1.click_id
                WHEN m2.rev_id > m1.rev_id AND m2.rev_id > m3.rev_id THEN m2.click_id
                ELSE m3.click_id
             END as click3
          FROM
             @matches m1
             CROSS JOIN @matches m2
             CROSS JOIN @matches m3
          WHERE
             m1.rev_id <> m2.rev_id
             AND m1.rev_id <> m3.rev_id
             AND m2.rev_id <> m3.rev_id
             AND m1.click_id <> m2.click_id
             AND m1.click_id <> m3.click_id
             AND m2.click_id <> m3.click_id
    ) t
)

SELECT
    rev1 as rev_id
    ,click1 as click_id
FROM
    cteOption
UNION ALL
SELECT
    rev2 as rev_id
    ,click2 as click_id
FROM
    cteOption
UNION ALL
SELECT
    rev3 as rev_id
    ,click3 as click_id
FROM
    cteOption

我确信有一种递归的方式也可以这样做,但我不知道红移是否支持这一点,而且还没有时间来追逐。

OLD:

如果您不关心哪个值,但是您只想保留每个rev_id值,那么您可以从评论中获取最高或最低值。

SELECT rev_id, MIN(click_id) as click_id FROM matches GROUP BY rev_id

OR

SELECT rev_id, MAX(click_id) as click_id FROM matches GROUP BY rev_id