简体   繁体   English

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

[英]Query with grouped results by column (SQL Server)

I've got a many to many relationship between items - itemnames - languages 我有一个许多人之间有很多关系items - itemnames - languages

The itemnames don't appear for every language. itemnames不会出现在所有的语言。

I'd like to get a result with all the items only represented once, but be able to set the languageId to default to. 我想得到一个只有一次表示的所有项目的结果,但是能够将languageId设置为默认值。

For example items 1,2,3 are defined in two languages, and item 4 and 5 have one language each, but the languages are different 例如,项目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

I'd like to create a query that only gives me one of each itemID , but allow me to specify which language to prefer , so if I select a languageID of 2, my query would only return item names for that start with 'leItem' with the exception of item 4, which should still give me item4 我想创建一个只给我一个itemID的查询,但允许我指定哪个语言更喜欢 ,所以如果我选择一个2的languageID ,我的查询只会返回'leItem'的那个开头的项目名称除了第4项,它仍然应该给我item4

Any ideas how to achieve this with a SELECT? 任何想法如何用SELECT实现这一点?

The theory (how I'm trying to get it to work), is that I create two queries, one for all where languageID matches x , and second where each item is represented (by group or distinct) and then merge the results. 理论(我是如何让它工作的)是,我创建了两个查询,一个用于languageID匹配x的所有查询,第二个用于表示每个项目(按组或不同),然后合并结果。


sql for generating the table 用于生成表的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])
);

You might be able to solve this with a subquery. 您可以使用子查询来解决此问题。 This might not be the best way way of solving it, but I'll take a stab at it. 这可能不是解决它的最佳方式,但我会采取措施。

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)

The first where condition is to provide all the entries that belongs to languageid = 2, the second part of the where conditions return true only if there isn't an entry with languageid = 2 for the current item you're looking at. 第一个条件是提供属于languageid = 2的所有条目,where条件的第二部分返回true,只有当你正在查看的当前项目没有languageid = 2的条目时才返回true。

http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html

I would try using a CASE statement. 我会尝试使用CASE语句。 Basically the idea is to determine if the preferred language exists and return null if it does not . 基本思路是,以确定是否首选语言存在,返回null ,如果它没有 That way you can utilize ISNULL to returned the preferred language (when it is populated) otherwise return the minimum language ID: 这样你就可以利用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 

this is how I'm handling it for now... 这就是我现在处理它的方式......

I've created a cffunction that loops through the query repeatedly. 我创建了一个循环遍历查询的cffunction。 It works, and because I'm sub-querying, I think performance should be ok. 它有效,因为我在查询,我认为性能应该没问题。 Seems like using a database side query might be too difficult for me. 似乎使用数据库端查询对我来说可能太难了。

<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