0

私は多対多の関係を持っていitemsますitemnames---languages

すべてのitemnames言語に表示されるわけではありません。

すべてのアイテムが1回だけ表示された結果を取得したいのlanguageIdですが、デフォルトに設定できます。

たとえば、項目1、2、3は2つの言語で定義されており、項目4と5にはそれぞれ1つの言語がありますが、言語は異なります。

[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

それぞれ1つだけを与えるクエリを作成したいのですitemIDが、どの言語を優先するかを指定できるので、2つを選択するlanguageIDと、クエリは「leItem」で始まるアイテム名のみを返します。項目4を除いて、それでも私に与えるはずですitem4

SELECTでこれを達成する方法はありますか?

理論(私がそれを機能させようとしている方法)は、2つのクエリを作成することです。1つはlanguageIDxに一致するすべてのクエリに対して、もう1つは各アイテムが(グループまたは個別に)表される場所で、結果をマージします。


テーブルを生成するための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に属するすべてのエントリを提供することであり、where条件の2番目の部分は、現在表示しているアイテムのlanguageid=2のエントリがない場合にのみ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場合は戻るという考え方です。そうすれば、優先言語を返すために利用できます(入力されている場合)。それ以外の場合は、最小言語IDを返します。ISNULL

// 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 に答える