基于列组合的SQL distinct/groupby

基于列组合的SQL distinct/groupby,sql,oracle,Sql,Oracle,我试图在基于两列的表上执行SQL选择,但不是以通常的方式,即两列中的值组合必须是唯一的;我想选择值在任一列中只能出现一次的位置。 给定数据集: |pkid | fkself | otherData | |-----+--------+-----------| | 1 | 4 | there | | 4 | 1 | will | | 3 | 6 | be | | 2 | 5 | other | | 5

我试图在基于两列的表上执行SQL选择,但不是以通常的方式,即两列中的值组合必须是唯一的;我想选择值在任一列中只能出现一次的位置。 给定数据集:

|pkid | fkself | otherData |
|-----+--------+-----------|
|  1  |   4    |   there   |
|  4  |   1    |    will   |
|  3  |   6    |     be    |
|  2  |   5    |    other  |
|  5  |   2    |   data    |
|  6  |   3    |  columns  |
我也要回去

|pkid | fkself | otherData |
|-----+--------+-----------|
|  1  |   4    |   there   |
|  3  |   6    |     be    |
|  2  |   5    |    other  |

我能想到的唯一方法是按顺序连接`pkid和fkid,以便第1行和第2行都连接到1,4,但我不确定如何连接,或者是否可能


这些行将具有其他数据列,但获取哪一行并不重要,只需获取每个ID一次,无论该值是在pkid中还是在fkself中

你的想法是可能的,它应该会产生你想要的结果

SELECT DISTINCT joinedID
FROM (
SELECT min(id) & "," & max(id) as joinedID
FROM (
    SELECT pkid as id, someUniqueValue 
    FROM table 
    UNION ALL 
    SELECT fkself as id, someUniqueValue 
    FROM table)
GROUP BY someUniqueValue )
这将为您提供一个唯一的ID列表,根据您的喜好进行连接。通过将其他字段添加到每个SELECT语句中,可以轻松地包含这些字段。此外,如果组合是唯一的,则someUniqueValue可以是现有的唯一字段、新的唯一字段或连接的pkid和fkself。

您可以使用最小值和最大值来获得两者中的最小值或最大值。这允许您将它们按正确的顺序排列,以便为您生成这些密钥。您可以按照建议连接这些值,但在本解决方案中不需要。使用稠密的_秩,您可以为每个虚构的密钥生成一个序列。然后,您可以从该序列中获取第一个其他数据

select
  pkid,
  fkself,
  otherData
from
  (select
    pkid,
    fkself,
    otherData,
    dense_rank() over (partition by least(pkid, fkself), greatest(pkid, fkself) order by pkid) as rank
  from
    YourTable t)
where
  rank = 1
我能想到的唯一方法就是将`pkid和 fkid,以便第1行和第2行都连接到1,4, 但我不知道如何做到这一点,或者这是否可能

您可以使用Oracle中的CASE语句执行此操作:

SQL> SELECT * FROM sample
  2  /

      PKID     FKSELF
---------- ----------
         1          4
         4          1
         3          6
         2          5
         5          2
         7          7

6 rows selected.

SQL> l
  1  SELECT DISTINCT *
  2  FROM (
  3  SELECT CASE WHEN pkid <= fkself THEN pkid||','||fkself
  4                                  ELSE fkself||','||pkid
  5         END "JOINED"
  6    FROM sample
  7* )
SQL> /

JOINED
-------------------------------------------------------------------------------
1,4
2,5
3,6
7,7

如果我正确理解了它的作用,我就不能这样做:从表t中选择pkid、fkself、otherData、dense_rank over partition by LeastChid、fkself、GreatestChid、fkself order by pkid作为秩,其中秩=1会给我一个额外的列,但在使用时可以忽略。我为Oracle数据库中的一个视图创建了这个语句。谢谢,这似乎是可行的。现在,我只需将其余的查询添加到它!您需要subselect,因为您不能在同一级别的where子句中使用秩。
SQL> SELECT * FROM sample
  2  /

      PKID     FKSELF
---------- ----------
         1          4
         4          1
         3          6
         2          5
         5          2
         7          7

6 rows selected.

SQL> l
  1  SELECT DISTINCT *
  2  FROM (
  3  SELECT CASE WHEN pkid <= fkself THEN pkid||','||fkself
  4                                  ELSE fkself||','||pkid
  5         END "JOINED"
  6    FROM sample
  7* )
SQL> /

JOINED
-------------------------------------------------------------------------------
1,4
2,5
3,6
7,7