在UNION ALL

时间:2015-11-01 05:50:10

标签: sql postgresql

SELECT _id, col1, col2, jobid, error_msg FROM table_name1
WHERE tn1.jobid in (1,2,3)
UNION ALL
SELECT _id, col1, col2, jobid, error_msg FROM table_name2
WHERE tn1.jobid in (1,2,3)
UNION ALL
SELECT _id, col1, col2, jobid, error_msg FROM table_name3
WHERE tn1.jobid in (1,2,3)

对于上述查询,输出将显示在下面

_id, col1, col2, jobid, error_msg
1, "Hi", "Hel", 1, "Data Invalid"
1, "Hi1", "Hel", 2, ""
2, "Hello", "DupTest",3, "" 
3, "Nota Dup", "All is Good",3 ,""

如果有重复项,我需要提出错误消息,对于上述情况_id(1)需要选择错误消息为“Duplicate Entries Present”

我的解决方案如下所示

WITH tmp AS
(
  SELECT _id , count(1) as cnt FROM
  (
    SELECT _id FROM table_name1
    WHERE tn1.jobid in (1,2,3)
    UNION ALL
    SELECT _id FROM table_name2
    WHERE tn1.jobid in (1,2,3)
    UNION ALL
    SELECT _id FROM table_name3
    WHERE tn1.jobid in (1,2,3) 
   )
   GROUP BY _id
)
SELECT _id, col1, col2, jobid, 
CASE WHEN tmp.cnt > 1 THEN "Dup present" ELSE NULL as error_msg
FROM table_name1
JOIN tmp USING(_id)
WHERE tn1.jobid in (1,2,3)
    UNION ALL
    SELECT _id, col1, col2, jobid
CASE WHEN tmp.cnt > 1 THEN "Dup present" ELSE NULL as error_msg
FROM table_name2
JOIN tmp USING(_id)
    WHERE tn2.jobid in (1,2,3)
    UNION ALL
    SELECT _id, col1, col2, jobid
CASE WHEN tmp.cnt > 1 THEN "Dup present" ELSE NULL as error_msg
FROM table_name3
JOIN tmp USING(_id)
    WHERE tn3.jobid in (1,2,3)

你能否建议有更好的解决方案呢?

可能还有一个选项将其创建为View以在多个位置使用它

CREATE TEMP VIEW tmp AS 
SELECT _id , count(1) as cnt FROM
      (
        SELECT _id FROM table_name1
        WHERE tn1.jobid in (1,2,3)
        UNION ALL
        SELECT _id FROM table_name2
        WHERE tn1.jobid in (1,2,3)
        UNION ALL
        SELECT _id FROM table_name3
        WHERE tn1.jobid in (1,2,3) 
       )
       GROUP BY _id

2 个答案:

答案 0 :(得分:0)

您可以使用窗口功能:

with cte as(SELECT _id, col1, col2, jobid, error_msg FROM table_name1
            WHERE tn1.jobid in (1,2,3)
            UNION ALL
            SELECT _id, col1, col2,jobid, error_msg FROM table_name2
            WHERE tn1.jobid in (1,2,3)
            UNION ALL
            SELECT _id, col1, col2,jobid, error_msg FROM table_name3
            WHERE tn1.jobid in (1,2,3))

select *, CASE WHEN count(*) over(partition by _id) > 1 
               THEN CONCAT_WS(',' , cte.error_msg, "Dup present")
               ELSE cte.error_msg
from cte

答案 1 :(得分:0)

窗口功能解决方案,Credit转到 Find duplicate rows with PostgreSQL

WITH tmp AS
(
  SELECT _id,
  ROW_NUMBER() OVER(PARTITION BY _id) AS cnt
  FROM
  (
    SELECT _id FROM table_name1
    WHERE tn1.jobid in (1,2,3)
    UNION ALL
    SELECT _id FROM table_name2
    WHERE tn1.jobid in (1,2,3)
    UNION ALL
    SELECT _id FROM table_name3
    WHERE tn1.jobid in (1,2,3) 
   )

)
SELECT _id, col1, col2, jobid, 
CASE WHEN tmp.cnt > 1 THEN "Dup present" ELSE NULL as error_msg
FROM table_name1
JOIN tmp USING(_id)
WHERE tn1.jobid in (1,2,3)
    UNION ALL
    SELECT _id, col1, col2, jobid
CASE WHEN tmp.cnt > 1 THEN "Dup present" ELSE NULL as error_msg
FROM table_name2
JOIN tmp USING(_id)
    WHERE tn2.jobid in (1,2,3)
    UNION ALL
    SELECT _id, col1, col2, jobid
CASE WHEN tmp.cnt > 1 THEN "Dup present" ELSE NULL as error_msg
FROM table_name3
JOIN tmp USING(_id)
    WHERE tn3.jobid in (1,2,3)