Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用内部联接的SQL查询_Sql_Sql Server_Sql Server 2008_Inner Join - Fatal编程技术网

使用内部联接的SQL查询

使用内部联接的SQL查询,sql,sql-server,sql-server-2008,inner-join,Sql,Sql Server,Sql Server 2008,Inner Join,分类表 Code Name 1 Food 2 Non-Food Tenant Code Tenant1 1,2 Tenant2 1 CREATE FUNCTION [dbo].[fnSplit] ( @String NVARCHAR(4000), @Delimiter NCHAR(1) ) RETURNS TABLE AS RETURN ( WITH Split(stpos,endpos)

分类表

   Code   Name
    1      Food
    2      Non-Food
Tenant    Code   
Tenant1   1,2    
Tenant2   1   
CREATE FUNCTION [dbo].[fnSplit]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH Split(stpos,endpos)
    AS(
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
        UNION ALL
        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
            FROM Split
            WHERE endpos > 0
    )
    SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
    FROM Split
)
CREATE FUNCTION [dbo].[GetCommaSeperatedCategory]
(
    @Codes VARCHAR(50)
)
RETURNS VARCHAR(5000)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @Categories VARCHAR(5000)

    SELECT @Categories= STUFF
                        (
                                (SELECT ',' + convert(varchar(10), Name, 120)
                                FROM Category
                                WHERE Code IN (SELECT Id FROM [dbo].[fnSplit] (@Codes,',') )
                                ORDER BY Code
                                FOR XML PATH (''))
                        , 1, 1, '') 

    RETURN @Categories

END
现有的表由类别列表组成,例如,我只有两个食物和非食物

作为挑战,我将为租户分配一个或多个类别(多重分配,因为有租户被分类为食物和非食物)。我曾经将租户和代码插入到创建此输出的新表中

租户签名表

   Code   Name
    1      Food
    2      Non-Food
Tenant    Code   
Tenant1   1,2    
Tenant2   1   
CREATE FUNCTION [dbo].[fnSplit]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH Split(stpos,endpos)
    AS(
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
        UNION ALL
        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
            FROM Split
            WHERE endpos > 0
    )
    SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
    FROM Split
)
CREATE FUNCTION [dbo].[GetCommaSeperatedCategory]
(
    @Codes VARCHAR(50)
)
RETURNS VARCHAR(5000)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @Categories VARCHAR(5000)

    SELECT @Categories= STUFF
                        (
                                (SELECT ',' + convert(varchar(10), Name, 120)
                                FROM Category
                                WHERE Code IN (SELECT Id FROM [dbo].[fnSplit] (@Codes,',') )
                                ORDER BY Code
                                FOR XML PATH (''))
                        , 1, 1, '') 

    RETURN @Categories

END
我需要做的是,将TenantAssingTable加载到gridview,该gridview包含CategoryCode的名称,如下所示

所需输出

   Tenant    CCode    Name
    Tenant1   1,2    Food,Non-Food
    Tenant2   1      Food
我在代码中使用了内部联接,但这是有限的,因为在代码列中有一个组合代码字符串

Select a.tenant, a.ccode, b.name
from TenantAssignTable a inner join CategoryTable b
on a.CCode = b.code
有没有办法实现这种产出?我知道这在SQL编码中是不寻常的,但这是一个挑战,因为所需的输出涉及到什么,需要什么,即为单个租户分配多个类别


提前谢谢

您可以使用一些XML转换:

DECLARE @x xml

SELECT @x = (
    SELECT CAST('<t name="'+a.tenant +'"><a>'+REPLACE(a.code,',','</a><a>') +'</a></t>' as xml)
    FROM TenantAssignTable a 
    FOR XML PATH('')
)

;WITH cte AS (
SELECT  t.v.value('../@name','nvarchar(max)') as Tenant,
        t.v.value('.','int') as CCode,
        ct.Name
FROM @x.nodes('/t/a') as t(v)
INNER JOIN CategoryTable ct
    ON ct.Code = t.v.value('.','int')
)

SELECT DISTINCT
            c.Tenant,
            STUFF((SELECT ','+CAST(CCode as nvarchar(10))
            FROM cte
            WHERE c.Tenant = Tenant
            FOR XML PATH('')
            ),1,1,'') as CCode,
            STUFF((SELECT ','+Name
            FROM cte
            WHERE c.Tenant = Tenant
            FOR XML PATH('')
            ),1,1,'') as Name
FROM cte c
第一部分(定义
@x
变量)将使您的表成为这种XML:

<t name="Tenant1">
  <a>1</a>
  <a>2</a>
</t>
<t name="Tenant2">
  <a>1</a>
</t>

1.
2.
1.

然后在CTE部分,我们将XML与类别表连接起来。毕竟,在FOR XML PATH的帮助下,从CTE获取数据。

创建如下函数,从分隔值返回表格

   Code   Name
    1      Food
    2      Non-Food
Tenant    Code   
Tenant1   1,2    
Tenant2   1   
CREATE FUNCTION [dbo].[fnSplit]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH Split(stpos,endpos)
    AS(
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
        UNION ALL
        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
            FROM Split
            WHERE endpos > 0
    )
    SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
    FROM Split
)
CREATE FUNCTION [dbo].[GetCommaSeperatedCategory]
(
    @Codes VARCHAR(50)
)
RETURNS VARCHAR(5000)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @Categories VARCHAR(5000)

    SELECT @Categories= STUFF
                        (
                                (SELECT ',' + convert(varchar(10), Name, 120)
                                FROM Category
                                WHERE Code IN (SELECT Id FROM [dbo].[fnSplit] (@Codes,',') )
                                ORDER BY Code
                                FOR XML PATH (''))
                        , 1, 1, '') 

    RETURN @Categories

END

创建如下函数,返回逗号分隔的名称

   Code   Name
    1      Food
    2      Non-Food
Tenant    Code   
Tenant1   1,2    
Tenant2   1   
CREATE FUNCTION [dbo].[fnSplit]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH Split(stpos,endpos)
    AS(
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
        UNION ALL
        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
            FROM Split
            WHERE endpos > 0
    )
    SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
    FROM Split
)
CREATE FUNCTION [dbo].[GetCommaSeperatedCategory]
(
    @Codes VARCHAR(50)
)
RETURNS VARCHAR(5000)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @Categories VARCHAR(5000)

    SELECT @Categories= STUFF
                        (
                                (SELECT ',' + convert(varchar(10), Name, 120)
                                FROM Category
                                WHERE Code IN (SELECT Id FROM [dbo].[fnSplit] (@Codes,',') )
                                ORDER BY Code
                                FOR XML PATH (''))
                        , 1, 1, '') 

    RETURN @Categories

END
最后一个:

SELECT
    Tenant,
    Code,
    (SELECT [dbo].[GetCommaSeperatedCategory] (Code)) AS Name
FROM TblTenant
简单思考

您可以使用
XML路径

DECLARE @CategoryTable TABLE (Code VARCHAR(50), Name VARCHAR(50))
INSERT INTO @CategoryTable
VALUES  
('1', 'Food'),
('2', 'Non-Food')

DECLARE @TenantAssignTable TABLE (Tenant VARCHAR(50), Code VARCHAR(50))
INSERT INTO @TenantAssignTable
VALUES  
('Tenant1', '1,2'),
('Tenant2', '1')

SELECT
    T.Tenant ,
    T.Code,
    STUFF(
        (SELECT
            ',' + C.Name
        FROM
            @CategoryTable C
        WHERE
            ',' + REPLACE(T.Code, ' ', '') + ',' LIKE '%,' + C.Code + ',%'
        FOR XML PATH('')
    ), 1, 1, '') A
FROM
    @TenantAssignTable T
结果:

Tenant          Code         A
--------------- ------------ ---------------
Tenant1         1,2          Food,Non-Food
Tenant2         1            Food   

您必须使用拆分函数,不要将这些代码存储为逗号分隔的项。这只会给你带来很多麻烦。我没有选择,但是@jarlh可以这样做。我已经有了一个拆分函数,但是不知道如何将它合并到代码@sandippatel中。你也可以进行嵌套替换,但是拆分函数更好。规范化您的数据将是最好的,但这听起来似乎超出了您的经验。你应该读一本关于数据库设计的书。WROX这本书很好。不错,但是如果我们在
@CategoryTable
('Tenant3','10')
中添加
。您的查询将返回
Tenant3 | 10 | Food,Something
:(您好@NEER我正在尝试您的代码,但它给了我以下错误:将数据类型varchar转换为数字时出错。您能显示表的列类型吗?我可以编辑答案。@NEER我已经得到了答案。但唯一的问题是A列结果在逗号后被如此多的空格分隔。示例:不是此输出:食物,非食物,而是resu是这样的:食物(很多空间),非食物类型的柱?