1

次のSQLServerテーブルがあります。

MyItemsTable(IDとLanguageIdはGUIDですが、説明を簡単にするためにここではintを使用します)

Id | Title | LanguageId
1 | My German Document 1 | 1
2 | My German Document 2 | 1
3 | My English Document 1 | 2
4 | My French Document 1 | 3

MyLanguagesTable

LanugageId | Code
1 | de-DE
2 | en-US
3 | fr-FR

MyItemsTableは、すべての言語で使用できる1つのドキュメント(Document 1)と、ドイツ語でのみ使用できる1つのドキュメント(Document2)があることを示しています。

今必要なのは、すべてのフランス語のドキュメントを配信するクエリです。たとえば、フランス語のドキュメントがない場合は、ドイツ語を教えてください。

フランス語の結果は次のようになります。

My French Document 1
My German Document 2

ドイツ語の結果は次のようになります。

My German Document 1
My German Document 2

解決すべきことが3つあると思います。

  1. 言語文書(他の言語に属するが他の言語に属する)の一体性を定義する
  2. 必要な言語で1つのドキュメントが利用できない場合は、順序を定義します。次にどちらをとるべきか。おそらく、最初のドキュメントを作成するときにMyItemsTableにフラグを立てる-> IsFirst = trueであり、この最初のドキュメントの言語ドキュメントを作成するときは、IsFirst=falseです。必要な言語のドキュメントが見つからない場合はIsFirst=trueを取得します->標準ドキュメントをマークするなど、他のドキュメントが利用できない場合はこれを取得します。
  3. たとえば、すべてのドキュメントをドイツ語で配信する簡単なクエリを作成し、1つのドキュメントが利用できない場合は、別の言語でドキュメントを配信します。

このようなものを簡単に構築する方法はありますか?シンプルで高速なソリューションのデータベーステーブルをどのように構築しますか(MyItemsTableとMyLanguagesTableは提供されていますが、変更できます)?

アイデアありがとうございます。

よろしくマーク

4

3 に答える 3

0

まず、言語に依存しないすべてのドキュメントのテーブルを用意し、次に言語のテーブルを用意する必要があります(各言語のiso値を使用することをお勧めします。これは、クリンゴン語の値もあるため、かなり包括的です)。次に、多対多のテーブル(実際には2つの1対多の関係の組み合わせ)各テーブルには、クラスター化インデックス、主キーと外部キー、および潜在的なクエリのインデックスを含める必要があります。これらの用語のいずれかが初めての場合は、http://www.w3schools.com/sql/のようにGoogleが友達です。これらの制約を使用して構築されたソリューションは、現実的な(SQL)データベースの能力を完全に損なうことになります

于 2013-03-26T09:49:56.147 に答える
0

ここに画像の説明を入力してください

同様のドキュメントのドキュメントタイプ平均を指定する列を追加する必要があります。だから私の場合、そのDOC_TYPE_ID

次に、次のクエリを使用してLANGUAGE_IDを送信します。つまり(1、2、3)


@LANGUAGE_IDINTを宣言します

SET @LANGUAGE_ID = 1; (値をドイツ語の場合は1、フランス語の場合は3、英語の場合は2に変更します)

WITH T(ID、DOC_TYPE_ID、TITLE、LANGUAGE_ID、DOCUMENT_RECORD_COUNT)AS(

SELECT d.ID、d.DOC_TYPE_ID、d.TITLE、d.LANGUAGE_ID、DENSE_RANK()OVER(PARTITION BY d.DOC_TYPE_ID ORDER BY d.LANGUAGE_ID DESC)AS DOCUMENT_RECORD_COUNT FROM [Document] d
WHERE 1 =(CASE WHEN @LANGUAGE_ID = 3 THEN CASE WHEN d.LANGUAGE_ID IN(1、3)THEN 1 ELSE 0 END WHEN @LANGUAGE_ID = 2 THEN CASE WHEN d.LANGUAGE_ID IN(1、2)THEN 1 ELSE 0 END WHEN d.LANGUAGE_ID = @LANGUAGE_ID THEN 1 ELSE 0 END)

)SELECT ID、DOC_TYPE_ID、TITLE、LANGUAGE_ID、DOCUMENT_RECORD_COUNT

FROM T WHERE DOCUMENT_RECORD_COUNT = 1 ORDER BY DOC_TYPE_ID

于 2013-03-26T10:11:29.113 に答える
0

言語に依存しないデータ(DocumentID、作成日、作成されたユーザーのドキュメントタイプなど)を含むようにドキュメントテーブルを再構築する必要があると思います。

次に、各言語のデータを含む別のテーブル(DocumentVersion)を作成します。ここで、documentidとlanguageIDが主キーを構成します。

DocumentID  |  LanguageID  |  Title  

ただし、言語コードは言語ごとに一意の値であるため、これを自然な主キーにします(または、sys.syslanguagesを使用できます)。これは、この問題に使用するデータ構造です。

CREATE TABLE Document
(       DocumentID      INT IDENTITY(1, 1) NOT NULL CONSTRAINT PK_Document_DocumentID PRIMARY KEY,
        DefaultTitle    VARCHAR(100) NOT NULL,
        CreatedDate     DATETIME NOT NULL
);
CREATE TABLE dbo.[Language]
(       LanguageCode    CHAR(5) NOT NULL CONSTRAINT PK_Lanaguage_LanguageCode PRIMARY KEY,
        Name            VARCHAR(50) NOT NULL,
        Alias           VARCHAR(50) NOT NULL
);
CREATE TABLE dbo.DocumentVersion
(       DocumentFK      INT NOT NULL,
        LanguageCode    CHAR(5) NOT NULL,
        Title           VARCHAR(50) NOT NULL
    CONSTRAINT PK_DocumentVersion PRIMARY KEY (DocumentFK, LanguageCode)
    CONSTRAINT FK_DocumentVersion_LanguageCode FOREIGN KEY (LanguageCode) REFERENCES dbo.[Language] (LanguageCode),
    CONSTRAINT FK_DocumentVersion_DocumentID FOREIGN KEY (DocumentFK) REFERENCES dbo.Document (DocumentID)
);
INSERT Document (DefaultTitle, CreatedDate) 
VALUES 
    ('Document 1', CURRENT_TIMESTAMP), 
    ('Document 2', CURRENT_TIMESTAMP);

INSERT dbo.[Language] (LanguageCode, Name, Alias)
VALUES 
    ('de-DE', 'Deutsch', 'German'), 
    ('en-US', 'US English', 'English'),  
    ('fr-FR', 'Français', 'French');

INSERT dbo.DocumentVersion (DocumentFK, LanguageCode, Title) 
VALUES
    (1, 'de-DE', 'My German Document 1'),
    (2, 'de-DE', 'My German Document 2'),
    (1, 'en-US', 'My English Document 1'),
    (1, 'fr-FR', 'My French Document 1')

あなたが言った方法でドキュメントを取得するには、正しい順序を取得するためのカスタムのcaseステートメントが必要になります。したがって、上記のサンプルを使用すると、

DECLARE @PrimaryLanguage CHAR(5) = 'fr-FR',
        @DefaultLanguage CHAR(5) = 'de-DE';

WITH RankedDocument AS
(   SELECT  DocumentFK, 
            LanguageCode, 
            Title,
            SortOrder = CASE WHEN LanguageCode = @PrimaryLanguage THEN 1 
                            WHEN LanguageCode = @DefaultLanguage THEN 2
                            -- MORE SORTING CRITERIA IF REQURED
                            ELSE 10
                        END
    FROM    DocumentVersion
), Docs AS
(   SELECT  d.DocumentID,
            rd.Title,
            d.CreatedDate,
            rn = ROW_NUMBER() OVER(PARTITION BY d.DocumentID ORDER BY rd.SortOrder)
    FROM    Document d
            INNER JOIN RankedDocument rd
                ON d.DocumentID = rd.DocumentFK
)
SELECT  DocumentID, Title, CreatedDate
FROM    Docs
WHERE   rn = 1;

フランス語のドキュメントの例

ドイツ語文書の例

編集

現在の構造でこれを行うには、フィールドを追加する必要があります。MyItemsTableこれは、デモンストレーションのために、おそらく新しいテーブルへの外部キーである必要がありLinkFieldます。

DECLARE @PrimaryLanguage INT = 1,
        @DefaultLanguage INT = 1;

WITH RankedItem AS
(   SELECT  ID, 
            Title, 
            LanguageId, 
            rn = ROW_NUMBER() OVER(PARTITION BY LinkField ORDER BY CASE LanguageId 
                                                                                WHEN @PrimaryLanguage THEN 1
                                                                                WHEN @DefaultLanguage THEN 2 
                                                                                ELSE 10 
                                                                            END)
    FROM    MyItemsTable
)
SELECT  ID, Title, LanguageID
FROM    RankedItem
WHERE   rn = 1;

SQLフィドルのデモ

于 2013-03-26T10:36:45.413 に答える