2016-12-26 43 views
9

Ví dụ:Làm cách nào để chọn khóa chính có khóa ngoài chính xác khớp với danh sách giá trị đã cho?

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

Làm thế nào để làm một truy vấn như "giả" truy vấn: kết quả truy vấn

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

Sự trở lại phải phù hợp với tất cả các giá trị nhất định cho chính nước ngoài trong danh sách.

Kết quả sẽ là:

1 

Trong khi chọn sau đây không phải trả lại bất kỳ hồ sơ.

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

Tôi làm như thế nào?

+0

bạn đang sử dụng SQL Server? –

+0

có, nhưng nếu có chuẩn sql bất kể động cơ db thì sẽ tốt hơn. –

+0

Danh sách giá trị fk "biến" được chuyển vào như thế nào? Một cách tiếp cận chung có thể là có một truy vấn phụ nơi bạn chọn pk, fk riêng biệt, nơi fk trong danh sách và trong truy vấn bên ngoài bạn nhóm theo pk và đếm các hàng. Nhưng đối với bộ lọc cuối cùng (mệnh đề HAVING), bạn cần phải biết có bao nhiêu giá trị trong danh sách, vì vậy bạn cần có khả năng đếm chúng. Vậy ... danh sách được đưa ra như thế nào? – mathguy

Trả lời

6

Hãy thử điều này

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 

Để làm điều đó tự động. (Xem xét bạn đang sử dụng SQL SERVER)

Tạo một hàm chuỗi phân chia và vượt qua các đầu vào như giá trị tách dấu phẩy

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 

Bạn có thể tạo một hàm split chuỗi từ liên kết dưới đây

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

+1

Tôi có số lượng giá trị không xác định, danh sách giá trị là biến thể. –

+0

@DevX - sau đó bạn cần sử dụng truy vấn động –

+0

cách thực hiện điều đó? –

2

Nếu bạn có thể chuyển giá trị toán tử IN làm Bộ, thì bạn có thể thực hiện như sau

Schema:

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 

Dùng CTE để làm cho 'a', 'c' như 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

:list là danh sách đầu vào (bind biến). Sự khác biệt của giá trị trả về length() là số lượng dấu phẩy trong biến liên kết. Truy vấn này, hoặc một cái gì đó rất gần với nó, nên làm việc trong khá nhiều bất kỳ sản phẩm DB. Thử nghiệm trong 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, ',', '')) 
+0

Tôi không nghĩ rằng điều này là hiệu quả ở tất cả. Nó trông đơn giản. Việc dẫn đầu '%' trong 'Like' sẽ làm cho truy vấn không thể sargable. –

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

hoặc

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

truy vấn cắt nhau là câu trả lời hoàn hảo, nhưng làm cách nào để làm cho truy vấn động này, vì vậy, bất kỳ số lượng giá trị nào có thể được chuyển cho nó, không chỉ cho hai biến như 'a' và 'c'? –

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 

    [email protected] 

    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 
Các vấn đề liên quan