Выделите все комбинации и покажите, которые не существуют - PullRequest
1 голос
/ 03 марта 2011

У меня есть три таблицы: X, Y и XY.Каждая таблица имеет поле с именем [Identity], которое является первичным ключом.(И поле автоинкремента.) В таблице XY есть два других поля: одно для ссылки на X, а другое для ссылки на Y. (Именованные [X_Identity] и [Y_Identity]) Комбинация этих ссылок представляет собой уникальный ключ.Таблица X имеет 6 полей (от X1 до X6), а таблица Y имеет 3 поля (от Y1 до Y3).Таблица XY имеет 4 поля, которые называются X2, X4, X5 и Y2.По назначению они похожи на поля в таблицах X или Y с одинаковыми именами.В таблице X будет около 200 записей, Y около 10 записей.Таблица XY содержит около 75 записей из возможных 2000 записей. Теперь моя проблема: Мне нужно представление, которое генерирует все 2000 комбинаций X и Y, и оно должно возвращать значения из записи XY, если существует запись для такой комбинации!Если нет, он должен просто объединить поля из X и Y. Таким образом, эта таблица имеет два возможных типа записей:

  • [X]. [X1], [X]. [X2], [X]. [X3], [X]. [X4], [X]. [X5], [X]. [X5], [Y] .Y1], [Y] .Y2], [Y] .Y3], если XY-запись не найдена.
  • [X]. [X1], [XY] . [X2], [X]. [X3], [XY] . [X4], [XY] . [X5], [X]. [X5], [Y] .Y1], [XY] .Y2], [Y] .Y3], если найдена существующая запись XY.

Сдается мне, я должен сделать объединение между выбором всех записей XY, чтобы получить половину результата.(Легко!) И мне нужно как-то объединить таблицы X и Y, для которых нет записи XY, чтобы сгенерировать вторую половину.И этот последний немного сложнее ... Предложения?О, и это будет только для чтения в моей системе!Так что это должен быть один оператор SQL!

Ответы [ 4 ]

2 голосов
/ 03 марта 2011

Я думал о создании перекрестного соединения X и Y, а затем заменил в наборе результатов значения, доступные в XY:

SELECT [X].[X1] AS [X1]
       ,COALESCE([XY].[X2], [X].[X2]) AS [X2]
       ,[X].[X3] AS [X3]
       ,COALESCE([XY].[X4], [X].[X4]) AS [X4]
       ,COALESCE([XY].[X5], [X].[X5]) AS [X5]
       ,[X].[X6] AS [X6]
       ,[Y].[Y1] AS [Y1]
       ,COALESCE([XY].[Y2], [Y].[Y2]) AS [Y2]
       ,[Y].[Y3] AS [Y3]
FROM [X]
CROSS JOIN [Y]
LEFT OUTER JOIN [XY]
ON [XY].[X_Identity] = [X].[Identity]
AND [XY].[Y_Identity] = [Y].[Identity]

Не пробовал, поэтомуможет понадобиться немного подправить.

1 голос
/ 03 марта 2011

Вот мой ответ.

SELECT [X].[X1] AS [X1]
       ,CASE WHEN XY.X_Identity is not null then [XY].[X2] else [X].[X2] end [X2]
       ,[X].[X3] AS [X3]
       ,CASE WHEN XY.X_Identity is not null then [XY].[X4] else [X].[X4] end [X4]
       ,CASE WHEN XY.X_Identity is not null then [XY].[X5] else [X].[X5] end [X5]
       ,[X].[X6] AS [X6]
       ,[Y].[Y1] AS [Y1]
       ,CASE WHEN XY.X_Identity is not null then [XY].[Y2] else [Y].[Y2] end [Y2]
       ,[Y].[Y3] AS [Y3]
FROM (X
CROSS JOIN Y)
LEFT OUTER JOIN XY
ON [XY].[X_Identity] = [X].[Identity]
AND [XY].[Y_Identity] = [Y].[Identity]

Это основано на прямом применении «CASE (pk) == существует» с использованием одного из ответов. Тем не менее, вы можете захотеть взглянуть на другую форму написания LEFT JOIN:

SELECT  [X].[X1]
       ,[XY].[X2]
       ,[X].[X3]
       ,[XY].[X4]
       ,[XY].[X5]
       ,[X].[X6]
       ,[Y].[Y1]
       ,[XY].[Y2]
       ,[Y].[Y3]
FROM (X
CROSS JOIN Y)
INNER JOIN XY ON [XY].[X_Identity] = [X].[Identity]
             AND [XY].[Y_Identity] = [Y].[Identity]

UNION ALL

SELECT  [X].[X1]
       ,[X].[X2]
       ,[X].[X3]
       ,[X].[X4]
       ,[X].[X5]
       ,[X].[X6]
       ,[Y].[Y1]
       ,[Y].[Y2]
       ,[Y].[Y3]
FROM (X
CROSS JOIN Y)
WHERE NOT EXISTS (
    SELECT * FROM XY
    WHERE [XY].[X_Identity] = [X].[Identity]
      AND [XY].[Y_Identity] = [Y].[Identity])
0 голосов
/ 03 марта 2011

Josien подошел ближе и дал мне идею второго решения, чтобы сделать это! Это не требует, чтобы я сделал вычисления и таким образом это немного более надежно. Но это все еще не очень красиво.

SELECT  
    [COMBI].[X1] AS [X1],
    COALESCE([XY].[X2], [COMBI].[X2]) AS [X2],
    [COMBI].[X3] AS [X3],
    COALESCE([XY].[X4], [COMBI].[X4]) AS [X4],
    COALESCE([XY].[X5], [COMBI].[X5]) AS [X5],
    [COMBI].[X6] AS [X6],
    [COMBI].[Y1] AS [Y1],
    COALESCE([XY].[Y2], [COMBI].[Y2]) AS [Y2],
    [COMBI].[Y3] AS [Y3]
FROM (
    SELECT 
        [X].[Identity] AS [X_Identity],
        [Y].[Identity] AS [Y_Identity],
        [X].[X1] AS [X1],
        [X].[X2] AS [X2],
        [X].[X3] AS [X3],
        [X].[X4] AS [X4],
        [X],[X5] AS [X5],
        [X].[X6] AS [X6],
        [Y].[Y1] AS [Y1],
        [Y].[Y2] AS [Y2],
        [Y].[Y3] AS [Y3]
    FROM 
        [X]
    CROSS JOIN 
        [Y]
} AS [COMBI]
LEFT OUTER JOIN 
    [XY]
ON 
    [XY].[X_Identity] = [COMBI].[X_Identity]
AND 
    [XY].[Y_Identity] = [COMBI].[Y_Identity]

Я действительно забыл о КОАЛЕССЕ. :-)

Единственное, что у него небольшая проблема! Хотя XY может иметь значение, одно из его полей все еще может иметь значение NULL. Если это так, он не переопределит значение из X или Y значением NULL из XY, но сохранит старое значение.
Поэтому это хорошее решение, но мне нужно переопределить значения из X и Y с помощью все значения из XY, даже если они равны NULL.

0 голосов
/ 03 марта 2011

Мне удалось найти решение, хотя и не слишком красивое:

SELECT 
    [X].[X1] AS [X1],
    [XY].[X2] AS [X2],
    [X].[X3] AS [X3],
    [XY].[X4] AS [X4],
    [XY].[X5] AS [X5],
    [X].[X6] AS [X6],
    [Y].[Y1] AS [Y1],
    [XY].[Y2] AS [Y2],
    [Y].[Y3] AS [Y3]
FROM 
    [X], 
    [Y],
    [XY]
WHERE
    [XY].[X_Identity] = [X].[Identity]
AND
    [XY].[Y_Identity] = [Y].[Identity]

UNION

SELECT 
    [X].[X1] AS [X1],
    [X].[X2] AS [X2],
    [X].[X3] AS [X3],
    [X].[X4] AS [X4],
    [X].[X5] AS [X5],
    [X].[X6] AS [X6],
    [Y].[Y1] AS [Y1],
    [Y].[Y2] AS [Y2],
    [Y].[Y3] AS [Y3]
FROM 
    [X], 
    [Y]
WHERE
    NOT (CAST([X].[Identity] AS nvarchar(12)) + '/' + CAST([Y].[Identity] AS nvarchar(12))) IN (
    SELECT
        CAST([XY].[X_Identity] AS nvarchar(12)) + '/' + CAST([XY].[Y_Identity] AS nvarchar(12))
    FROM 
        [XY]
    ))

Это объединение двух операторов выбора (и даже третьего), где первый выбирает все записи из XY и добавляетсоответствующие данные из таблиц X и Y к нему.Второй выбор выполняет некоторые дополнительные вычисления, чтобы объединить таблицы X и Y в одно поле, которое я могу найти в таблице XY, выполнив там те же вычисления.Хотя это работает, мне просто интересно, можно ли это сделать проще ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...