如何选择具有精确外键的主键与给定的值列表匹配?

时间:2016-12-26 04:13:07

标签: mysql sql sql-server oracle

例如:

pk_ref    fk
======    ===
1         a
1         b
1         c
2         a
2         b
2         d

如何进行“伪”查询之类的查询:

select distinc pk_ref
where fk in all('a', 'c');

返回查询结果必须与列表中外键的所有给定值匹配。

结果应为:

1

以下选择不得返回任何记录。

select distinc pk_ref
where fk in all('a', 'c', 'd');

我该怎么做?

5 个答案:

答案 0 :(得分:6)

试试这个

select pk_ref 
from yourtable 
group by pk_ref 
having count(case when fk = 'a',  then 1 end) >= 1 
and count(case when fk = 'c' then 1 end) >= 1

动态地做。 (考虑到你使用的是SQL SERVER)

创建拆分字符串函数并将输入作为逗号分隔值

传递
Declare @input varchar(8000)= 'a,c',@cnt int 

set @cnt = len(@input)-len(replace(@input,',','')) + 1

select pk_ref 
from yourtable 
Where fk in (select split_values from udf_splitstring(@input , ','))
group by pk_ref 
having count(Distinct fk) >= @cnt 

您可以从以下链接

创建拆分字符串功能

https://sqlperformance.com/2012/07/t-sql-queries/split-strings

答案 1 :(得分:3)

:list是输入列表(绑定变量)。 length()返回值的差异是绑定变量中逗号的数量。此查询或与其非常接近的查询应该适用于任何数据库产品。在Oracle中测试过。

select   pk_ref
from     tbl    --  enter your table name here
where    ',' || :list || ','   like   '%,' || fk || ',%'
group by pk_ref
having   count(distinct fk) = 1 + length(:list) - length(replace(:list, ',', ''))

答案 2 :(得分:2)

如果您可以将IN运算符值作为Set传递,则可以执行以下操作

架构:

SELECT * INTO #TAB FROM (
SELECT 1 ID, 'a' FK
UNION ALL
SELECT 1, 'b'
UNION ALL
SELECT 1, 'c'
UNION ALL
SELECT 2, 'a'
UNION ALL
SELECT 2, 'b'
UNION ALL
SELECT 2, 'd'
UNION ALL
SELECT 1, 'a'
)AS A

使用CTE来制作'' c'如Set

;WITH CTE AS (
SELECT 'a' FK   --Here 'a','c' passed as a Set through CTE
UNION 
SELECT 'c'
)
,FINAL AS(

SELECT DENSE_RANK() OVER (PARTITION BY ID ORDER BY (FK))AS COUNT_ID, ID, FK 
FROM #TAB where FK  IN (select FK FROM CTE)

)
SELECT ID FROM FINAL WHERE COUNT_ID>=(SELECT COUNT( FK) FROM CTE)

答案 3 :(得分:1)

Select pk_ref where fk='a' and pk_ref in (select pk_ref where fk='c' from yourtable) from yourtable;  

select pk_ref where fk='a' from yourtable intersect select pk_ref where fk='c' from yourtable;

答案 4 :(得分:0)

    DECLARE @inputVariable VARCHAR(200) =  'a,b,c,d'
    DECLARE @inputValue INT
    DECLARE @tblInput TABLE
    (
        FK VARCHAR(100)
    )




    INSERT INTO @tblInput
    SELECT SUBSTRING( @inputVariable+',',RN,1)
      FROM (SELECT TOP 100 ROW_NUMBER() OVER(ORDER BY s.object_id) RN
      FROM sys.objects s)  s
      where LEN(@inputVariable) >= RN
      AND SUBSTRING(','+ @inputVariable,RN,1) = ','

    SELECT @inputValue = COUNT(1) FROm @tblInput

    --@inputVariable

    DECLARE @tbl TABLE 
    (
        ID INT,
        FK VARCHAR(100) 
    )

    INSERT INTO @tbl
    SELECT 1 ID, 'a' FK
    UNION ALL
    SELECT 1, 'b'
    UNION ALL
    SELECT 1, 'c'
    UNION ALL
    SELECT 2, 'a'
    UNION ALL
    SELECT 2, 'b'
    UNION ALL
    SELECT 2, 'd'
    UNION ALL
    SELECT 1, 'a'

    SELECT t.ID ,COUNT(DISTINCT t.FK) 
      FROM @tbl t
    INNER JOIn @tblInput  ti
            ON t.FK = ti.FK
        GROUP BY ID
        HAVING COUNT(DISTINCT t.FK) = @inputValue