SQL - Как комбинация из 13 числительных c столбцов равняется 1 столбцу - PullRequest
2 голосов
/ 03 февраля 2020

У меня есть таблица с 14 цифрами c столбцов. Каким-то образом; добавляя, вычитая или игнорируя каждый из первых 13 столбцов, я хочу, чтобы комбинация равнялась 14-му столбцу. Я хочу выяснить, что нужно добавить, что нужно вычесть и что нужно игнорировать, чтобы получить 14-й столбец.

Например, если бы у меня было 6 столбцов (вместо 14), решение могло бы быть COLUMN1 + COLUMN2 - COLUMN3 + (0 * COLUMN4) + COLUMN5

Чтобы при запуске:

SELECT COUNT(*) FROM TABLE 
WHERE COLUMN1 + COLUMN2 - COLUMN3 + (0*COLUMN4) + COLUMN5 != COLUMN6

я получал 0.

Какой самый эффективный способ достижения этого? Я готов позволить этому запускаться в течение нескольких часов, если необходимо.

Я использую SQL server 2016

Ответы [ 3 ]

2 голосов
/ 03 февраля 2020

Это совершенно новый ответ.

Идея состоит в том, чтобы развернуть, а затем снова присоединиться к нему несколько раз. Вот пример с 3 столбцами, а не с 13:

with tcols as (
      select t.id, t.col14, v.which, v.col, v2.sign
      from t cross apply
           (values (1, t.col1), (2, t.col2), (3, t.col3)) v(which, col) cross apply
           (values (-1), (1), (0)) v2(sign)
     )
select *
from tcols tc1 join
     tcols tc2
     on tc2.id = tc1.id and tc1.which = 1 and tc2.which = 2 join
     tcols tc3
     on tc3.id = tc2.id and tc3.which = 3
where (tc1.sign * tc1.col) + (tc2.sign * tc2.col) + (tc3.sign * tc3.col) = tc1.col14;

Очевидно, что расширение этого требует добавления дополнительных объединений.

Здесь - это db <> fiddle

Будет ли это работать на 13 столбцах? Количество сравнений для каждого идентификатора составляет 3 ^ 13 = 1,594,323. Это много, но, вероятно, не выходит за рамки современных баз данных.

1 голос
/ 04 февраля 2020

Я предлагаю сначала получить все возможные факторы -1, 0 и 1 на позицию. Например:

-1, -1, -1, -1, -1
-1, -1, -1, -1,  0
-1, -1, -1, -1, +1
-1, -1, -1,  0, -1
-1, -1, -1,  0,  0
-1, -1, -1,  0, +1
...

Затем умножьте каждый фактор на каждое значение и посмотрите, получите ли вы желаемый результат.

Я использую рекурсивный запрос для построения факторов. Для простоты здесь я использую шесть значений (пять операндов и один результат).

with singlefactors (factor) as
(
  select -1 union all select 0 union all select 1
)
, cte (f1, f2, f3, f4, f5, num) as
(
  select factor, 0, 0, 0, 0, 1 from singlefactors
  union all
  select
    cte.f1,
    case when cte.num = 1 then singlefactors.factor else cte.f2 end,
    case when cte.num = 2 then singlefactors.factor else cte.f3 end,
    case when cte.num = 3 then singlefactors.factor else cte.f4 end,
    case when cte.num = 4 then singlefactors.factor else cte.f5 end,
    cte.num + 1
  from cte
  cross join singlefactors
  where cte.num < 5
)
, factors as
(
  select f1, f2, f3, f4, f5 from cte where num = 5
)
select *
from mytable m
join factors f on m.col1 * f.f1 + m.col2 * f.f2 +
                  m.col3 * f.f3 + m.col4 * f.f4 +
                  m.col5 * f.f5 = m.col6
order by m.col1, m.col2, m.col3, m.col4, m.col5, m.col6, f.f1, f.f2, f.f3, f.f4, f.f5;

Результат:

+ -----+------+------+------+------+------+----+----+----+----+----+
| col1 | col2 | col3 | col4 | col5 | col6 | f1 | f2 | f3 | f4 | f5 |
+ -----+------+------+------+------+------+----+----+----+----+----+
| 1    | 2    | 3    | 4    | 5    | 6    | -1 | -1 |  0 |  1 |  1 |
| 1    | 2    | 3    | 4    | 5    | 6    | -1 |  0 |  1 |  1 |  0 |
| 1    | 2    | 3    | 4    | 5    | 6    | -1 |  1 |  0 |  0 |  1 |
| ...  |      |      |      |      |      |    |    |    |    |    |
+ -----+------+------+------+------+------+----+----+----+----+----+

Демонстрация: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=872201f49f9cace4ad62be59465bca87

Возможно, вы хотите, чтобы результат выглядел несколько лучше, но это не должно быть слишком сложно, чтобы выполнить sh отсюда.

0 голосов
/ 03 февраля 2020

Вы пробуете?

SELECT COUNT(*) FROM TABLE WHERE ((COLUMN1 + (COLUMN2 - (COLUMN3 + (0*COLUMN4)))) + COLUMN5) != COLUMN6 

Возможно, создаст проблемы с суммой и вычитанием

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