向SQL窗口函数添加条件语句

时间:2020-01-27 18:32:09

标签: sql postgresql conditional-statements window-functions

我想使用一系列条件来决定我拥有的窗口函数的工作方式。目前,我的状态是:

SELECT col1, col2, 
   1=Row_number() OVER (PARTITION BY col1 ORDER BY col2 ASC) OR
   3=Row_number() OVER (PARTITION BY col1 ORDER BY col2 ASC)
   AS col3 
FROM   myTable;

它实际上是在进行两列输入,按col1中的值分组,按col2中的值排序,然后将每个分区的数据分为两半,并标记每半的第一行为true / 1。

因此,请输入以下内容:

+------+------+
| col1 | col2 |
+------+------+
|    1 |    1 |
|    1 |    2 |
|    1 |    3 |
|    1 |    4 |
|    2 |    1 |
|    2 |    2 |
|    2 |    3 |
|    2 |    4 |
+------+------+

我们得到以下结果:

+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
|    1 |    1 |    1 |
|    1 |    2 |    0 |
|    1 |    3 |    1 |
|    1 |    4 |    0 |
|    2 |    1 |    1 |
|    2 |    2 |    0 |
|    2 |    3 |    1 |
|    2 |    4 |    0 |
+------+------+------+

现在,很明显,这仅在col1中每个值正好有4行条目的情况下起作用。当不完全是4行时,我该如何引入条件语句来使之起作用?

我的约束是这些:

a) there will always be an even number of rows (2,4,6..) when grouping by values in `col1`
b) there will be a minimum of 2 rows when grouping by values in `col1`

编辑:

我想我需要澄清的是,我不只是希望交替排列1和0。例如,如果我改用此表...

+------+------+
| col1 | col2 |
+------+------+
|    1 |    1 |
|    1 |    2 |
|    1 |    3 |
|    1 |    4 |
|    1 |    5 |
|    1 |    6 |
|    1 |    7 |
|    1 |    8 |
|    2 |    1 |
|    2 |    2 |
|    2 |    3 |
|    2 |    4 |
|    2 |    5 |
|    2 |    6 |
|    2 |    7 |
|    2 |    8 |
+------+------+

...那么我希望得到这个结果:

+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
|    1 |    1 |    1 |
|    1 |    2 |    0 |
|    1 |    3 |    0 |
|    1 |    4 |    0 |
|    1 |    5 |    1 |
|    1 |    6 |    0 |
|    1 |    7 |    0 |
|    1 |    8 |    0 |
|    2 |    1 |    1 |
|    2 |    2 |    0 |
|    2 |    3 |    0 |
|    2 |    4 |    0 |
|    2 |    5 |    1 |
|    2 |    6 |    0 |
|    2 |    7 |    0 |
|    2 |    8 |    0 |
+------+------+------+

在我给出的原始示例中,我们按col1分组,发现每个分区有4行。我们取其中一半,即2,并将第二行(每隔一行)标记为true / 1。

在第二个示例中,一旦按col1分组,我们看到每个分区有8行。将其分成两半可得到4,因此每4行应标记为true / 1。

2 个答案:

答案 0 :(得分:2)

使用模运算。

SQL的许多方言都使用%作为模数:

SELECT col1, col2, 
       ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col2) % 2 as col3
FROM mytable;

某些使用功能MOD()

SELECT col1, col2, 
       MOD(ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col2), 2) as col3
FROM mytable;

编辑:

您不想替换行。您只需要两行。为此,您仍然可以使用取模算法,但逻辑有所不同:

SELECT col1, col2, 
       (ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col2) %
        FLOOR(COUNT(*) OVER (PARTITION BY col1) / 2)
       ) as col3
FROM mytable;

答案 1 :(得分:1)

我只是扩大戈登的答案,因为他的答案不会给您正确的结果-

SELECT col1, col2, 
       (CASE WHEN ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col2) %
        FLOOR(COUNT(*) OVER (PARTITION BY col1) / 2) = 1 THEN 1 ELSE 0 END 
       ) as col3
FROM mytable;