0

我有一个多对多的关系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,但允许我指定首选哪种语言,所以如果我选择languageID2,我的查询将只返回以“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])
);
4

3 回答 3

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

于 2012-04-20T01:42:52.523 回答
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 
于 2012-04-24T15:15:47.433 回答
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>
于 2012-04-20T17:12:33.897 回答