КРОМЕ показа дополнительных полей

Допустим, у меня есть две таблицы (из загруженных файлов CSV), и я хочу выполнить разницу на основе идентификатора + территории в новом файле, которого не было в старом файле. Самый простой способ сделать это - это что-то вроде:

SELECT id, territory FROM this_week EXCEPT SELECT id, territory FROM last_week

Однако я пытаюсь получить ВСЕ поля (в обеих таблицах - по одной строке на ключ), которые генерируются этой разницей. Как это можно сделать?

Подойдет либо postgres, либо bigquery. У обоих есть набор EXCEPT op.


Пример с данными из ответа Эрвина:

WITH this_week (id,territory,name,other) AS (VALUES(1,'us','titanic','uhd'),(22,'us','spider','hd'),(3,'fr','new','hd')),
     last_week (id,territory,name,other) AS (VALUES(1,'us','titanic','uhd'),(2,'us','spider','hd'))
SELECT *  -- all columns of "this_week"
FROM   this_week t
WHERE  NOT EXISTS (
   SELECT * FROM last_week l
   WHERE  t.id = l.id
   AND    t.territory = l.territory
   );

🤔 А знаете ли вы, что...
SQL позволяет объединять данные из разных таблиц с помощью операторов JOIN.


61
2

Ответы:

Решено

Используйте НЕ СУЩЕСТВУЕТ:

SELECT *  -- all columns of "this_week"
FROM   this_week t
WHERE  NOT EXISTS (
   SELECT FROM last_week l
   WHERE  t.id = l.id
   AND    t.territory = l.territory
   );

А индекс last_week (id, territory) обычно помогает производительности (очень сильно).

Здесь показаны все столбцы this_week.
. Я не вижу смысла добавлять столбцы last_week, которые были бы пустыми (null) по определению запроса, если бы вы присоединились слева.

Основы:

Обратите внимание на тонкую разницу:

EXCEPT (при использовании без ALL) складывает дубликаты. Этот запрос не делает. Вы можете хотеть того или другого. Обычно вы этого хотите.


Сравнение двух одинаково структурированных таблиц (с одинаковыми именами столбцов в одном и том же порядковом положении) с первичным ключом (уникальным и не допускающим значения NULL) pk:

SELECT t1.*
    , t2.*
FROM Table1 t1
FULL JOIN Table2 t2
    ON t1.pk = t2.pk
WHERE NOT EXISTS(
    SELECT t1.*
    INTERSECT
    SELECT t2.*
    )

Это даст вам все различия между двумя таблицами. Если в обеих таблицах есть совпадающий pk, вы увидите записи, где остальные столбцы где-то отличаются. Если строка находится в t1, а не в t2 (по pk), она появится, если строка находится в t2, а не в t1 (по pk), она появится.

Если таблицы не имеют идентичной структуры, вам нужно будет расширить * в подзапросе и явно перечислить столбцы, которые вы хотите сравнить.

Пример

--Create two identically strctured tables
CREATE TABLE Table1(PK BIGINT NOT NULL
                    , Col1 BIGINT
                    , Col2 BIGINT
                    )
;

CREATE TABLE Table2(PK BIGINT NOT NULL
                    , Col1 BIGINT
                    , Col2 BIGINT
                    )
;

--insert some data into them
INSERT INTO Table1(PK
                , Col1
                , Col2 
                )
VALUES
    (1, 100, 1000) --Pk In both Table1 and Table2, and contents match
    ,(2, 101, 1001) --Pk In both Table1 and Table2, and contents do not match
    ,(3, 102, 1002) --Pk only in Table1
;

INSERT INTO Table2(PK
                , Col1
                , Col2 
                )
VALUES
    (1, 100, 1000) --Pk In both Table1 and Table2, and contents match
    ,(2, 0, 0) --Pk In both Table1 and Table2, and contents do not match
    ,(4, 103, 1003) --Pk only in Table2
;

--Compare them
SELECT CASE 
        WHEN t1.PK IS NULL --This assumes that PK being NULL is due to the JOIN only!
            THEN 'In Table2, and not in Table1'
        WHEN t2.pk IS NULL --This assumes that PK being NULL is due to the JOIN only!
            THEN 'In Table1, and not in Table2'
        ELSE 'In both tables, but contents differ'
    END AS ComparisonDescription
    , t1.*
    , t2.*
FROM Table1 t1
FULL JOIN Table2 t2
    ON t1.pk = t2.pk
WHERE NOT EXISTS(
    SELECT t1.* --IF not identically structured, select the common columns here
    INTERSECT
    SELECT t2.* --IF not identically structured, select the common columns here
    )
;

Db<>Fiddle с примером