有沒有辦法在單個 SQL 語句中確保列表中的所有項目都出現在某個列中?
我正在尋找的是一種驗證所有項目列表(比如說“FOO”、“BAR”和“BAZ”)是否都在給定的 table.column 中的方法。這就像 SELECT something FROM sometable WHERE somevalue IN (‘THIS’, ‘THAT’, ‘OTHER THING’) … 除了它有點相反:
理想情況下,該語句將為我提供 (‘FOO’, ‘BAR’, ‘BAZ’) NOT IN sometable.somecolumn 中的所有內容,然後我可以將其用作我的檢查(斷言我的 SQL 查詢返回一個空集或獲取結果集和抱怨每個都是“無法辨識”的密鑰)。(蠻力方法是將所有術語/標籤/項目插入到一個臨時的單列表中,並在我的實際表的列上為不在其中的行集執行 JOIN。
我確定我錯過了一些語法技巧,一旦我看到一個例子就會很明顯。
在這種特殊情況下,我的表結構類似於:
CREATE TABLE items (id INTEGER PRIMARY KEY, item TEXT UNIQUE NOT NULL); CREATE TABLE tags (tag_id INTEGER PRIMARY KEY, tag TEXT UNIQUE NOT NULL); CREATE TABLE item_tag (item_id integer, tag_id integer, FOREIGN KEY(item_id) REFERENCES items(id), FOREIGN KEY(tag_id) REFERENCES tags(tag_id), PRIMARY KEY (item_id, tag_id));
…但我只是想提出一個模板來獲取任意數量的“標籤”並確保它們都是“tags.tag”列的有效條目。(應用程序必須支持對這些標籤子集的任意複雜查詢以返回項目的 DISTINCT 子集;但我想在建構 JOIN 的 WHERE 表達式之前對任何不存在的標籤提出錯誤)。
顯然我可以遍歷標籤做一個單獨的 SELECT tag_id FROM tags where tag=? … 需要多次往返數據庫。但是當我可以在一條語句中將它們全部發送到某種查詢時,這似乎很愚蠢。
如果我了解您要實現的目標,那麼我認為您想要的是一個 CTE,其中包含您要比較的所有可能標籤的 UNION 列表,然後將標籤表與 CTE 右連接。
例子 -
WITH ListOfTags (Tag) AS (SELECT 'Foo' UNION SELECT 'bar' UNION SELECT 'other' UNION SELECT 'thing') SELECT * FROM item_tag i INNER JOIN tags t ON i.tag_id = t.tag_id RIGHT JOIN ListOfTags l ON l.Tag like t.tag WHERE i.item_id is null
這可能不是最優雅的方式,但它可能對你有用
我不會以任何方式呼叫這種語法糖,但在 Oracle 中,您可以在這樣的查詢中將標籤作為分隔列表傳遞:
SELECT a.Data FROM ( SELECT SUBSTR(main_string, position_from + 1, position_to - position_from - 1) Data FROM ( SELECT main_string, DECODE(rownum - 1, 0, 0, instr(main_string, ',', 1, rownum - 1)) position_from, instr(main_string, ',', 1, rownum) position_to FROM (SELECT 'FOO,BAR,BAZ,' main_string FROM dual) CONNECT BY LEVEL <= LENGTH(main_string) ) WHERE position_to > 0` ) a WHERE NOT EXISTS (SELECT 1 FROM Tags WHERE Tag = a.Data) ;