[英]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.