Sql Server选择查询的特殊用法

时间:2013-03-26 09:17:03

标签: sql sql-server select

我有以下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

MyLanguagesTable

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. 如果一个文档不适用于所需的语言,则定义订单。接下来应该采取哪种措施。在创建第一个文档时可能在MyItemsTable上创建一个标志 - > IsFirst = true,在创建第一个文档的语言文档时,IsFirst = false。如果找不到所需语言的文档,则取IsFirst = true - >比如标记标准文档,如果另一个文档不可用则采用此文件。
  3. 创建一个简单的查询,例如以德语提供所有文档,如果一个文档不可用,则以其他语言提供文档。
  4. 有没有想法如何以简单的方式构建这样的东西?如何为简单快速的解决方案构建数据库表(给出MyItemsTable和MyLanguagesTable但可以修改)?

    非常感谢您的任何想法。

    祝你好运 马克

3 个答案:

答案 0 :(得分:0)

首先你应该拥有一个独立于语言的所有文档的表,然后有一个语言表(我建议使用每种语言的iso值:这是非常全面的,因为klingon还有一个值)然后你需要一个多对多的表(实际上是两个一对多关系的组合),每个表应该有聚簇索引,主键和外键,以及覆盖潜在查询的索引。如果这些条款中的任何一项对您来说都是新的,那么谷歌就是您的朋友http://www.w3schools.com/sql/。使用这些约束构造时的解决方案将完全实现realtional(SQL)数据库的强大功能

答案 1 :(得分:0)

enter image description here

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

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


  

DECLARE @LANGUAGE_ID INT

     

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   (由d.LANGUAGE_ID DESC划分d.DOC_TYPE_ID订购)AS   DOCUMENT_RECORD_COUNT来自[文件] d
  在哪里1 =(当@LANGUAGE_ID = 3时为例当d.LANGUAGE_ID为   (1,3)那么1 0结束                     当@LANGUAGE_ID = 2时那么d.LANGUAGE_ID在(1,2)那么1节0结束                     当d.LANGUAGE_ID = @LANGUAGE_ID那么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

答案 2 :(得分: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;

<强> Example with French Documents

<强> Example with German Documents

修改

要使用当前结构执行此操作,您需要向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;

<强> Demo on SQL Fiddle