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

时间:2012-04-20 01:28:23

标签: sql sql-server coldfusion

我在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,但允许我指定更喜欢的语言,所以如果我选择{{1} 2,我的查询只返回那个以“leItem”开头的项目名称,项目4除外,它仍然应该给我languageID

有关如何使用SELECT实现此目的的任何想法吗?

理论(我是如何让它工作的)是我创建了两个查询,一个用于item4匹配x的所有查询,第二个用于表示每个项目(按组或不同)然后合并结果。


用于生成表的SQL

languageID

3 个答案:

答案 0 :(得分:1)

您可以使用子查询来解决此问题。这可能不是解决它的最佳方式,但我会采取措施。

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

答案 1 :(得分:1)

我会尝试使用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 

答案 2 :(得分:0)

这就是我现在处理它的方式......

我已经创建了一个循环遍历查询的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>