[英]Query with grouped results by column (SQL Server)
我有一個許多人之間有很多關系items
- itemnames
- languages
該itemnames
不會出現在所有的語言。
我想得到一個只有一次表示的所有項目的結果,但是能夠將languageId
設置為默認值。
例如,項目1,2,3以兩種語言定義,項目4和5各有一種語言,但語言不同
[itemid][languageid][name]
1, 1, item1
1, 2, leItem1
2, 1, item2
2, 2, leItem2
3, 1, item3
3, 2, leItem3
4, 1, item4
5, 2, leItem5
我想創建一個只給我一個itemID
的查詢,但允許我指定哪個語言更喜歡 ,所以如果我選擇一個2的languageID
,我的查詢只會返回'leItem'的那個開頭的項目名稱除了第4項,它仍然應該給我item4
任何想法如何用SELECT實現這一點?
理論(我是如何讓它工作的)是,我創建了兩個查詢,一個用於languageID
匹配x的所有查詢,第二個用於表示每個項目(按組或不同),然后合並結果。
用於生成表的sql
-- Languages
CREATE TABLE [Languages] (
[id] INT NOT NULL PRIMARY KEY IDENTITY,
[language] NVARCHAR(20) NOT NULL ,
[languagecode] NVARCHAR(6) NOT NULL
);
-- Items
CREATE TABLE [Items] (
[id] INT NOT NULL PRIMARY KEY IDENTITY,
[ImageId] INT ,
[lastupdate] DATETIME,
[isactive] BIT NOT NULL DEFAULT 'TRUE'
);
-- ItemNames
CREATE TABLE [ItemNames] (
[itemId] INT NOT NULL ,
[languageId] INT NOT NULL ,
[name] NVARCHAR(50) NOT NULL ,
FOREIGN KEY (itemId) REFERENCES Items(id),
FOREIGN KEY (languageId) REFERENCES Languages(id),
PRIMARY KEY ([itemId],[languageId])
);
您可以使用子查詢來解決此問題。 這可能不是解決它的最佳方式,但我會采取措施。
SELECT DISTINCT
outer.itemid,
outer.languageid,
outer.name
FROM
table AS outer
WHERE
outer.languageid = 2
OR NOT EXIST (SELECT * FROM table AS inner WHERE languageid = 2 AND inner.itemid = outer.itemid)
第一個條件是提供屬於languageid = 2的所有條目,where條件的第二部分返回true,只有當你正在查看的當前項目沒有languageid = 2的條目時才返回true。
http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html
我會嘗試使用CASE
語句。 基本思路是,以確定是否首選語言存在,返回null
,如果它沒有 。 這樣你就可以利用ISNULL
返回首選語言(當它被填充時),否則返回最小語言ID:
// replace @preferred with the preferred language id ie 2
SELECT itn.ItemID, itn.LanguageID, itn.Name
FROM ItemNames itn INNER JOIN
(
SELECT itemID,
// use preferred language if it exists
// otherwise, use the minimum languageID
ISNULL( MIN ( CASE WHEN LanguageID = @preferred THEN LanguageID ELSE NULL END )
, MIN (LanguageID)
) AS LanguageID
FROM ItemNames
GROUP BY itemID
)
sel ON sel.ItemID = itn.ItemID AND sel.LanguageID = itn.LanguageID
這就是我現在處理它的方式......
我創建了一個循環遍歷查詢的cffunction。 它有效,因為我在查詢,我認為性能應該沒問題。 似乎使用數據庫端查詢對我來說可能太難了。
<cffunction name="getLanguageUniqueEntries" output="no" returntype="query" >
<cfargument name="q" Type="query" required="true">
<cfargument name="languageId" Type="string" required="true">
<cfargument name="uniqueColumn" Type="string" required="false" default="ID">
<!--- Copy structure, assume table has an id column where no item matches -1 --->
<cfquery dbtype="query" name="newQ"> SELECT * FROM q WHERE #uniqueColumn# = -1 </cfquery>
<!--- get list of unigue IDs --->
<cfquery dbtype="query" name="uniquePropertyIDs"> SELECT #uniqueColumn# FROM q GROUP BY #uniqueColumn# </cfquery>
<!--- loop through unique IDs ---->
<cfloop query="uniquePropertyIDs">
<cfset colIdVal = uniquePropertyIDs[uniqueColumn][uniquePropertyIDs.CurrentRow]>
<!--- find row in language --->
<cfquery dbtype="query" name="currentLangQ" maxrows="1">
SELECT * FROM q WHERE #uniqueColumn# = #colIdVal# AND LanguageID = #languageId#
</cfquery>
<cfif currentLangQ.recordcount NEQ 0>
<!--- insert row --->
<cfquery dbtype="query" name="newQ"> SELECT * FROM newQ UNION SELECT * FROM currentLangQ </cfquery>
<cfelse>
<!--- entry in language not found, get a default value --->
<cfquery dbtype="query" name="anyLangQ" maxrows="1"> SELECT * FROM q WHERE #uniqueColumn# = #colIdVal# ORDER BY LanguageID</cfquery>
<!--- insert row --->
<cfquery dbtype="query" name="newQ"> SELECT * FROM newQ UNION SELECT * FROM anyLangQ</cfquery>
</cfif>
</cfloop>
<cfreturn newQ>
</cffunction>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.