繁体   English   中英

SQL Server选择查询的特殊用法

[英]Sql Server select query for a special usage

我有以下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)以所有语言提供,而一个文档(Document2)仅以德语提供。

我现在需要的是一个查询,其中提供了所有法语文件,如果没有可用的法语文件,请给我一个德语。

法语的结果应如下所示:

My French Document 1
My German Document 2

德语的结果应如下所示:

My German Document 1
My German Document 2

我认为有三件事要解决:

  1. 定义语言文档的统一性(属于另一个文档,但使用其他语言)
  2. 如果一个文档不能用于所需的语言,请定义顺序。 接下来应该采取。 创建第一个文档-> IsFirst = true时,可能会在MyItemsTable上做一个标记,而当创建第一个文档的语言文档时,则IsFirst = false。 如果未找到所需语言的文档,则采用IsFirst = true->将标准文档标记为类似内容,如果其他文档不可用,则采用此方法。
  3. 创建一个简单的查询,例如以德语提供所有文档,如果一个文档不可用,则以另一种语言提供文档。

是否有任何想法如何轻松构建这样的东西? 您将如何为简单而快速的解决方案构建数据库表(给出了MyItemsTable和MyLanguagesTable,但可以对其进行修改)?

非常感谢您的任何想法。

最好的问候马克

好吧,首先,您应该有一个与语言无关的所有文档表,然后有一个语言表(我建议对每种语言使用iso值:这是非常全面的,因为klingon也有一个值),然后您需要多对多表(实际上是两个一对多关系的组合),每个表应具有聚簇索引,主键和外键,并涵盖潜在查询的索引。 如果您对这些条款不熟悉,则google和http://www.w3schools.com/sql/都是您的朋友。 在具有这些约束条件的情况下构造的解决方案将完全影响实际(SQL)数据库的功能

在此处输入图片说明

您需要添加一列,以指定类似文档的文档类型。 所以我的情况是DOC_TYPE_ID

现在使用以下查询仅发送LAN​​GUAGE_ID,即(1、2、3)


十进制@LANGUAGE_ID INT

SET @LANGUAGE_ID = 1; (将值1更改为德语,将3更改为法语,将2更改为英语)

带有T(ID,DOC_TYPE_ID,TITLE,LANGUAGE_ID,DOCUMENT_RECORD_COUNT)的AS(

从[文档] d中选择d.ID,d.DOC_TYPE_ID,d.TITLE,d.LANGUAGE_ID,DENSE_RANK()超过(按d.DOC_TYPE_ID顺序按d.LANGUAGE_ID DESC顺序分配)
1 =(@LANGUAGE_ID = 3时的情况,然后d.LANGUAGE_ID IN(1,3)然后1的情况,然后@LANGUAGE_ID = 2然后d.LANGUAGE_ID IN(1,2)时的情况,然后1否则0结束的情况d.LANGUAGE_ID = @LANGUAGE_ID THEN 1 ELSE 0 END)

)SELECT ID,DOC_TYPE_ID,TITLE,LANGUAGE_ID,DOCUMENT_RECORD_COUNT个

从T WHERE DOCUMENT_RECORD_COUNT = 1 ORDER BY DOC_TYPE_ID

我认为您应该重组文档表,使其仅包含独立于语言的数据(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小提琴演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM