2013-01-17 52 views
1

我有一個包含一個表格和兩列的搜索查詢。需要編輯多個列的SQL搜索查詢

Select * 
from Gecoserv _a 
where _a.typeOfEcosystem IN (:typeNameList) 
    AND _a.service IN (:serviceNameList) 

它的工作原理,但它沒有給我想要

結果

比方說:

typeNameList = { Freshwater, Saltwater, Dunes } 
serviceNameList = {Habitat, Food, Recreation } 

我想要的表格顯示只有單一的組合(淡水人居署,鹽水,食品和沙丘休閒等),但它也顯示了其他組合(例如:淡水休閒)。

換句話說:查詢結果顯示

[0,0],[0,1],[0,2], 
[1,0],[1,1],[1,2], 
[2,0],[2,1],[2,2]. 

但我只想看到:[0,0],[1,1],[2,2]

我知道我必須添加一些東西到查詢的最後。我嘗試了很多東西,但都找不到一個完美的解決方案。

有沒有人可以幫助我呢?

問候,

Melih

+0

做你的表有獨特的鍵(或其他標識列):其它技術(只是普通的老神在讀),可以發現? – wildplasser

回答

0

我覺得這個不能做,如果這是你得到的唯一信息。參數值之間的關係是它們在列表中的位置。在SQL中沒有選擇關聯和/或保留這些位置。

你對創建sql語句有什麼影響?

如果你可以遍歷代碼列表和動態創建的SQL,你能來這樣一個解決方案:

SELECT * FROM Gecoserv 
    WHERE typeOfEcosystem = 'Freshwater' AND service = 'Habitat' 
UNION 
SELECT * FROM Gecoserv 
    WHERE typeOfEcosystem = 'Freshwater' AND service = 'Food' 
UNION 
... 

有關如何參數化這樣的一個例子,看看this answer

一種替代方案:拆分字符串

你的主要問題是,維護「等級」 /在他們的名單參數的「位置」。這可以通過用字符串替換您的列表並將其分解來完成。

我用這個example of a splitting a string in sql

(與this Fiddle製造)生成的查詢則是這樣的:

DECLARE 
    @ecoSystems varchar(100) = 'Freshwater,Saltwater,Dunes', 
    @services varchar(100) = 'Habitat,Food,Recreation', 
    @separator char(1) = ',' 

SELECT 
    [g].[id], 
    [g].[typeOfEcoSystem], 
    [g].[service] 
FROM [dbo].[Split](@separator, @ecoSystems) [e] 
INNER JOIN [dbo].[Split](@separator, @services) [s] 
    ON [e].[position] = [s].[position] 
INNER JOIN [Gecoserv] [g] 
    ON [e].[part] = [g].[typeOfEcoSystem] 
    AND [s].[part] = [g].[service] 
ORDER BY [id] ASC 

將這項工作對於您的情況?(答:是的,幾乎...)

最後沒有一個功能

DECLARE 
    @ecoSystems varchar(100) = 'Freshwater,Saltwater,Dunes', 
    @services varchar(100) = 'Habitat,Food,Recreation', 
    @separator char(1) = ','; 

WITH [EcoSystemsAndServices]([posE], [startE], [endE], [posS], [startS], [endS]) 
AS 
(
    SELECT 
    1, 
    1, 
    CHARINDEX(@separator, @ecoSystems), 
    1, 
    1, 
    CHARINDEX(@separator, @services) 
    UNION ALL 
    SELECT 
    [posE] + 1, 
    [endE] + 1, 
    CHARINDEX(@separator, @ecoSystems, [endE] + 1), 
    [posS] + 1, 
    [endS] + 1, 
    CHARINDEX(@separator, @services, [endS] + 1) 
    FROM [EcoSystemsAndServices] 
    WHERE [endE] > 0 
) 


SELECT 
    [g].[id], 
    [g].[typeOfEcoSystem], 
    [g].[service] 
FROM [Gecoserv] [g] 
INNER JOIN [EcoSystemsAndServices] [ess] 
    ON [g].[typeOfEcoSystem] = SUBSTRING(@ecoSystems, 
             [startE], 
             CASE WHEN [endE] > 0 THEN [endE] - [startE] ELSE 100 END) 
    AND [g].[service] = SUBSTRING(@services, 
            [startS], 
            CASE WHEN [endS] > 0 THEN [endS] - [startS] ELSE 100 END) 
ORDER BY [id] ASC 
+0

感謝您的回答。但是,我想要做的不是一個接一個地寫元素。你寫的第一個查詢很好,但應該有一種方法來獲取具有相同等級的元素。 (例如:typeNameList [4]和serviceList [4]或typeNameList [28]和serviceList [28])所以,我在尋找的是查詢使我們能夠從數組變量中選擇項目; typeNameList和serviceNameList。但訣竅是元素應該具有相同的等級。 –

+0

我添加了一個替代我的答案。你可以刪除你的答案,這是一個意見? – Jacco

+0

非常感謝。是的,這適用於我的情況。但是我們有一個問題。問題是我一直在Wavemaker中編寫代碼,而我正在使用HQL而不是SQL。我想我可以通過修改HQL上的SQL查詢來申請。但我不知道是否可以在HQL上創建一個函數。我已經搜索了這個,但找不到任何有用的信息。在這種情況下你有什麼建議嗎? –

0

沒有任何後備方案,甚至是數據庫廠商,我的回答將不得不作出有關您的設置一些假設。

理論

這聽起來極像是一個笛卡爾乘積。問題的癥結在於你的IN子句彼此獨立。因此,單個記錄可以滿足這兩個條件,但不是您想要在結果集中看到的內容。舉個例子說,我們有一個記錄如下:

id name   typeOfEcosystem service 
-- ------------ --------------- ---------- 
1 myEcoService Freshwater  Recreation 

您的查詢,因爲它是現在寫的,會先採取typeOfEcosystem(淡水),並檢查它是否在你的列表中,它是。 結果:TRUE

然後,查詢將採取服務(Recreation)並檢查它是否在第二個列表中。再次,價值被發現。 結果:TRUE

所有條件的計算結果都爲true,因此該行包含在最終結果集中。

解決方案

像你想要條款A多列這聽起來我。請注意,這與您的嘗試截然不同,因爲最終解決方案應該只涉及一個IN關鍵字。現在,查詢的確切形式將取決於您的數據庫以及它提供的內容。適用於任何符合SQL的數據庫的解決方案是使用字符串操作。一個粗略的例子如下:

Select * 
    from Gecoserv _a 
where _a.typeOfEcosystem || '-' || _a.service IN ('Freshwater-Habitat', 'Saltwater-Food', 'Dunes-Recreation') 

在這個例子中,'||'被假定爲串聯。這非常便攜,但速度很慢。這個問題可以更加優雅地解決,但確切的解決方案將取決於您的特定數據庫和要求。

Select * 
    from Gecoserv _a 
where (_a.typeOfEcosystem, _a.service) IN (('Freshwater', 'Habitat'), ('Saltwater', 'Food'), ('Dunes', 'Recreation')); 

您可能需要按摩這些解決方案,讓他們與你的DBMS以及玩:例如,如第一個多列在Oracle中可能是那樣簡單。

  1. SQL multiple columns in IN clause

  2. Select records where a combinations of columns are repeated using SQLite

+0

感謝您的回答。但是,我想要做的不是一個接一個地寫元素。你寫的第一個查詢很好,但應該有一種方法來獲取具有相同等級的元素。 (例如:typeNameList [4]和serviceList [4]或typeNameList [28]和serviceList [28]) 所以,我在尋找的是查詢使我們能夠從數組變量中選擇項目; typeNameList和serviceNameList。但訣竅是元素應該具有相同的等級。 –