繁体   English   中英

按列分组查询结果(SQL Server)

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM