1

我有以下 SQL Server 表:

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

我的语言表

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

MyItemsTable 显示有一份文档(文档 1)提供所有语言版本,一份文档(文档 2)仅提供德语版本。

我现在需要的是一个提供所有法语文档的查询,如果没有可用的法语文档,那么给我例如德语。

法语的结果应如下所示:

My French Document 1
My German Document 2

德语的结果应如下所示:

My German Document 1
My German Document 2

我认为要解决三个问题:

  1. 定义语言文档的整体性(属于其他语言但使用其他语言)
  2. 如果一份文档不适用于所需语言,请定义顺序。接下来应该采取哪个。可能在创建第一个文档时在 MyItemsTable 上创建一个标志 -> IsFirst = true 并且在创建第一个文档的语言文档时 IsFirst = false。如果没有找到所需语言的文档,则采用 IsFirst = true -> 类似标记标准文档并在另一个不可用时采用此文档。
  3. 创建一个简单的查询,例如以德语提供所有文档,如果一个文档不可用,则提供另一种语言的文档。

有什么想法如何以简单的方式构建这样的东西吗?您将如何为简单快速的解决方案构建数据库表(MyItemsTable 和 MyLanguagesTable 已给出但可以修改)?

非常感谢您的任何想法。

最好的问候马克

4

3 回答 3

0

那么首先你应该有一个独立于语言的所有文档的表,然后有一个语言表(我建议对每种语言使用 iso 值:这是非常全面的,因为克林贡语也有一个值)然后你需要一个多对多表(实际上是两个一对多关系的组合)每个表都应该有聚集索引、主键和外键,以及潜在查询的覆盖索引。如果您对这些术语中的任何一个不熟悉,那么 google 就像http://www.w3schools.com/sql/一样是您的朋友。使用这些约束构建的解决方案将充分发挥 Realtional (SQL) 数据库的功能

于 2013-03-26T09:49:56.147 回答
0

在此处输入图像描述

您需要添加一个 Column 来指定类似文档的文档类型。所以在我的情况下它的 DOC_TYPE_ID

现在使用以下查询来发送 LANGUAGE_ID 即 (1, 2, 3)


声明 @LANGUAGE_ID INT

设置@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 结束)

) 选择 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')

为了以您所说的方式获取文件,您需要一个自定义案例声明才能获得正确的订单。因此,对于上面的示例,您可以使用

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 Fiddle 演示

于 2013-03-26T10:36:45.413 回答