Использование кортежей в SQL в пункте
Учитывая базу данных, как это:
BEGIN TRANSACTION;
CREATE TABLE aTable (
a STRING,
b STRING);
INSERT INTO aTable VALUES('one','two');
INSERT INTO aTable VALUES('one','three');
CREATE TABLE anotherTable (
a STRING,
b STRING);
INSERT INTO anotherTable VALUES('one','three');
INSERT INTO anotherTable VALUES('two','three');
COMMIT;
Я хотел бы сделать что-то вроде
SELECT a,b FROM aTable
WHERE (aTable.a,aTable.b) IN
(SELECT anotherTable.a,anotherTable.b FROM anotherTable);
Чтобы получить ответ "один", "три", но я получаю "рядом", ": синтаксическая ошибка"
Это возможно в любой разновидности SQL? (Я использую sqlite)
Я делаю грубую концептуальную ошибку? Или что?
3 ответа
Ваш код работает, если вы делаете это в PostgreSQL или Oracle. на MS SQL не поддерживается
использовать этот:
SELECT a,b FROM aTable
WHERE
-- (aTable.a,aTable.b) IN -- leave this commented, it makes the intent more clear
EXISTS
(
SELECT anotherTable.a,anotherTable.b -- do not remove this too, perfectly fine for self-documenting code, i.e.. tuple presence testing
FROM anotherTable
WHERE anotherTable.a = aTable.a AND anotherTable.b = aTable.b
);
[РЕДАКТИРОВАТЬ]
без указания намерения:
SELECT a,b FROM aTable
WHERE
EXISTS
(
SELECT *
FROM anotherTable
WHERE anotherTable.a = aTable.a AND anotherTable.b = aTable.b
);
Это несколько неубедительно, вот уже более десяти лет MS SQL по-прежнему не имеет первоклассной поддержки кортежей. Конструкция IN tuple более удобочитаема, чем аналогичная конструкция EXISTS. Кстати, JOIN также работает (код tster), но если вам нужно что-то более гибкое и ориентированное на будущее, используйте EXISTS.
[РЕДАКТИРОВАТЬ]
Говоря о SQLite, я в последнее время балуюсь этим. да, IN кортежей не работает
Вы можете использовать соединение:
SELECT aTable.a, aTable.b FROM aTable
JOIN anotherTable ON aTable.a = anotherTable.a AND aTable.b = anotherTable.b
Другой альтернативой является использование конкатенации, чтобы превратить ваш 2-кортеж в одно поле:
SELECT a,b FROM aTable
WHERE (aTable.a||'-'||aTable.b) IN
(SELECT (anotherTable.a || '-' || anotherTable.b FROM anotherTable);
... просто знайте, что плохие вещи могут случиться, если a или b содержат разделитель '-'