我有3张相关的表格。一个表有我正在寻找的行,另一个表有我需要搜索的数据,第三个表描述了我要查找的数据。我从以下查询中得到了不受欢迎的结果:
SELECT * FROM names WHERE namesKey IN ( SELECT namesKey FROM data WHERE
( dataType IS 3 AND data IS 'COINCIDENCE' )
AND ( dataType IS 2 AND data IS 'STATE' )
AND ( dataType IS 1 AND data IS 'COUNTRY' ) );
我需要帮助根据过滤器表中的多行进行查询。我需要与第二个表中存在于多行上的键对应的行...我说的很糟糕......这是一个例子:
DROP TABLE IF EXISTS names ;
CREATE TABLE names (
namesKey INTEGER PRIMARY KEY ASC,
name TEXT NOT NULL
);
DROP TABLE IF EXISTS data ;
CREATE TABLE data (
dataKey INTEGER PRIMARY KEY ASC,
namesKey INTEGER NOT NULL,
dataType INTEGER NOT NULL,
data TEXT NOT NULL,
FOREIGN KEY(namesKey) REFERENCES names(namesKey)
);
DROP TABLE IF EXISTS filter ;
CREATE TABLE filter (
filterKey INTEGER PRIMARY KEY ASC,
dataType INTEGER NOT NULL,
data TEXT NOT NULL
);
INSERT INTO names( name ) VALUES ( 'name1' );
INSERT INTO names( name ) VALUES ( 'name2' );
INSERT INTO names( name ) VALUES ( 'name3' );
INSERT INTO names( name ) VALUES ( 'name4' );
INSERT INTO names( name ) VALUES ( 'name5' );
INSERT INTO names( name ) VALUES ( 'name6' );
INSERT INTO names( name ) VALUES ( 'name7' );
INSERT INTO names( name ) VALUES ( 'name8' );
INSERT INTO names( name ) VALUES ( 'name9' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 1, 1, 'COUNTRY' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 1, 2, 'STATE' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 1, 3, 'CITY' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 2, 1, 'COUNTRY' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 2, 2, 'STATE' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 2, 3, 'OTHERCITY' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 3, 1, 'COUNTRY' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 3, 2, 'STATE' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 3, 3, 'COINCIDENCE' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 4, 1, 'COUNTRY' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 4, 2, 'OTHERSTATE' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 4, 3, 'COINCIDENCE' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 5, 1, 'OTHERCOUNTRY' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 5, 2, 'RANDOM' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 5, 3, 'COINCIDENCE' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 6, 1, 'OTHERCOUNTRY' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 6, 2, 'OTHERSTATE' );
INSERT INTO data( namesKey, dataType, data ) VALUES ( 6, 3, 'COINCIDENCE' );
INSERT INTO filter( dataType, data ) VALUES ( 1, 'COUNTRY' );
INSERT INTO filter( dataType, data ) VALUES ( 2, 'STATE' );
INSERT INTO filter( dataType, data ) VALUES ( 3, 'COINCIDENCE' );
现在我需要的是能够相对可靠地运行3种不同类型的查询。
我需要搜索"无数据"并获得名称7,8和9
这个很容易:
SELECT * FROM names WHERE namesKey NOT IN ( SELECT namesKey FROM data ) ;
我需要根据数据表中的单一类型数据进行搜索
同样简单,期望的结果3,4,5和6
SELECT * FROM names WHERE
namesKey IN ( SELECT namesKey FROM data WHERE
( dataType IS 3 AND data IS 'COINCIDENCE' ) )
;
我需要根据过滤表中的多行进行搜索。这个我不知道怎么做......
我可以通过
来完成SELECT * FROM names WHERE
namesKey IN ( SELECT namesKey FROM data WHERE
( dataType IS 3 AND data IS 'COINCIDENCE' ) )
AND
namesKey IN ( SELECT namesKey FROM data WHERE
( dataType IS 2 AND data IS 'STATE' ) )
AND
namesKey IN ( SELECT namesKey FROM data WHERE
( dataType IS 1 AND data IS 'COUNTRY' ) )
;
更糟糕的是,使用这种方法,dataType在理论上是任意大的,因此我可能最终会尝试将数十个甚至数百个子查询串起来...我甚至在尝试之前我只能编写我的字符串。把它放到SQL中。 所以我正在寻找更优雅的解决方案。有什么建议?
答案 0 :(得分:2)
如果我理解正确,您可以使用:
float:left;
的 SqlFiddleDemo
强>
输出:
SELECT *
FROM names
WHERE namesKey IN (SELECT namesKey
FROM data
WHERE dataType IS 3 AND data IS 'COINCIDENCE'
INTERSECT
SELECT namesKey
FROM data
WHERE dataType IS 2 AND data IS 'STATE'
INTERSECT
SELECT namesKey
FROM data
WHERE dataType IS 1 AND data IS 'COUNTRY'
);
或使用聚合:
╔═══════════╦═══════╗
║ namesKey ║ name ║
╠═══════════╬═══════╣
║ 3 ║ name3 ║
╚═══════════╩═══════╝
的 SqlFiddleDemo2
强>
答案 1 :(得分:1)
您可以直接将过滤器表与实际表连接以获取具有匹配项的行,然后仅检查所有三个搜索项匹配的那些名称键,即匹配行数与该数字相同的组所有搜索值:
SELECT namesKey
FROM data
JOIN filter USING (dataType, data)
GROUP BY namesKey
HAVING COUNT(*) = (SELECT COUNT(*) FROM filter);
然后像往常一样使用这些名称:
SELECT *
FROM names
WHERE namesKey IN (SELECT namesKey...);