2012-04-20 83 views
0

我有一个多对多的关系items之间 - itemnames - languages查询与列(SQL Server)的分组结果

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,但允许我指定哪种语言更喜欢,所以如果我选择languageID为2,我的查询只会返回以'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]) 
); 
+0

什么是所涉及的实际表(无图)。另外,如下所述,如果有多种非首选语言会发生什么? – Leigh 2012-04-20 03:24:30

+0

这些是实际的表,如果有多个它应该得到最低的ID – Daniel 2012-04-20 15:17:21

回答

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 
+0

谢谢!!!看起来像这样 – Daniel 2012-04-24 18:27:23

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) 

第一个where条件是为所有属于languageid = 2的条目,只有当不存在与languageid = 2当前项目条目的where条件的第二部分返回true你正在看。

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

+0

谢谢大卫,我通过视图处理第一组连接,所以子查询是不可避免的。我想我最感兴趣的领域是'WHEN'后面我会给这个修补程序 – Daniel 2012-04-20 01:49:48

+0

完全,请让我知道这是如何为你工作的! – 2012-04-20 01:55:02

+2

如果在数据集中引入了第三种语言,比如说'4,3,Foobar4',那么这个查询将返回第4项的两行。 – 2012-04-20 02:02:54

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> 
+0

我不认为你需要跳过这样的箍环:)。如果您发布涉及的表格的ddl,我们可以提供更具体的建议。 – Leigh 2012-04-20 17:27:19

+0

如何获取dll? – Daniel 2012-04-20 19:54:38

+0

使用管理工作室生成[DDL](http://en.wikipedia.org/wiki/Data_Definition_Language#CREATE_statements)。 – Leigh 2012-04-20 20:06:18