我有以下场景,一个包含以下列的表:
table_id|user_id|os_number|inclusion_date
在系统中,os_number对用户来说是连续的,但由于系统错误,一些用户以错误的顺序插入操作系统。像这样:
table_id | user_id | os_number | inclusion_date
-----------------------------------------------
1 | 1 | 1 | 2015-11-01
2 | 1 | 2 | 2015-11-02
3 | 1 | 3 | 2015-11-01
我需要什么:
恢复第2行和第3行的table_id,这是乱序的。
我有两个选择以两个不同的顺序向我显示table_id:
select table_id from table order by user_id, os_number
select table_id from table order by user_id, inclusion_date
我无法弄清楚如何比较这两个选项,看看哪些用户受到此系统错误的影响。
答案 0 :(得分:2)
您的问题有点困难,因为没有正确的排序(如所示) - 因为日期可以有关系。因此,使用rank()
或dense_rank()
函数比较两个值并返回不正确顺序的值:
select t.*
from (select t.*,
rank() over (partition by user_id order by inclusion_date) as seqnum_d,
rank() over (partition by user_id order by os_number) as seqnum_o
from t
) t
where seqnum_d <> seqnum_o;
答案 1 :(得分:1)
对两个订单使用row_number()
:
select *
from (
select *,
row_number() over (order by os_number) rnn,
row_number() over (order by inclusion_date) rnd
from a_table
) s
where rnn <> rnd;
table_id | user_id | os_number | inclusion_date | rnn | rnd
----------+---------+-----------+----------------+-----+-----
3 | 1 | 3 | 2015-11-01 | 3 | 2
2 | 1 | 2 | 2015-11-02 | 2 | 3
(2 rows)
答案 2 :(得分:1)
不完全确定此方面的性能,但您可以在同一个表上使用交叉应用以在一个查询中获得结果。这将调出不正确的table_ids对。
select
a.table_id as InsertedAfterTableId,
c.table_id as InsertedBeforeTableId
from table a
cross apply
(
select b.table_id
from table b
where b.inclusion_date < a.inclusion_date and b.os_number > a.os_number
) c
答案 3 :(得分:0)
我会使用WINDOW FUNCTIONS
获取相关订单中的row numbers,然后对其进行比较:
new width
修改强>
由于a_horse_with_no_name对我的最终答案有所了解。我回到了我的第一个答案(查看编辑历史记录),如果SELECT
sub.table_id,
sub.user_id,
sub.os_number,
sub.inclusion_date,
number_order_1, number_order_2
FROM (
SELECT
table_id,
user_id,
os_number,
inclusion_date,
row_number() OVER (PARTITION BY user_id
ORDER BY os_number
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
) AS number_order_1,
row_number() OVER (PARTITION BY user_id
ORDER BY inclusion_date
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
) AS number_order_2
FROM
table
) sub
WHERE
number_order_1 <> number_order_1
;
没有无间隙,那么该工作也会有效。
答案 4 :(得分:0)
下面给出的两个查询示例只是检查包含日期和os_number之间的不匹配:
第一个查询应返回有问题的行(os_number从其包含日期开始关闭的行) - 在示例行3的情况下。
select table.table_id, table.user_id, table.os_number from table
where EXISTS(select * from table t
where t.user_id = table.user_id and
t.inclusion_date > table.inclusion_date and
t.os_number < table.os_number);
第二个查询将返回两个不匹配行的表号和用户:
select first_table.table_id, second_table.table_id, first_table.user_id from
table first_table
JOIN table second_table
ON (first_table.user_id = second_table.user_id and
first_table.inclusion_date > second_table.inclusion_date and
first_table.os_number < second_table.os_number);
答案 5 :(得分:0)
select *
from (
select a_table.*,
lag(inclusion_date) over (partition by user_id order by os_number) as last_date
from a_table
) result
where last_date is not null AND last_date>inclusion_date;
这应该包括差距和关系。基本上,我只是检查最后一个os_number的inclusion_date,并确保它不是严格地大于当前日期(所以同一日期的2个版本没问题)。