基于列连接表而不为每个组合创建记录

时间:2012-03-20 07:29:02

标签: sql-server vb.net asp.net-3.5

我有两张表如下:

Customer | Product
------------------
    A    |   Car
    A    |  Bike
    A    |  Boat
    B    |   Foo
    B    |   Bar

Customer | Friends
------------------
    A    |   John
    A    |  Andrew
    B    |   Baz

对于每个客户,我想显示购买的产品列表,以及这样的朋友列表:

Customer   Products    Friends
------------------------------
A       - Car       - John
        - Bike      - Andrew
        - Boat
------------------------------
B       - Foo       - Baz
        - Bar     

如果我使用普通JOIN,那么我会获得每个单独产品的朋友列表。我只想要两个列表。

带有' - '的输出列表不一定是表格单元格,它们可以是<ul> s。

我怎样才能做到这一点?我想绑定到ASP.net GridView。我应该尝试在一个查询中完成所有操作,还是使用多个查询并以某种方式将它们添加到同一个网格中?


每行实际上都是长报告的一部分。基本上,报告的每一行都包含客户ID,一堆与客户ID一对一匹配的其他字段,然后是我描述的每个客户ID的两个列表。也许我可以为每个列表使用单独的查询,然后手动将每个列表添加到RowDataBound或类似的网格上?

3 个答案:

答案 0 :(得分:3)

写这篇文章我觉得很脏。这是丑陋的代码,因为应该如何使用SQL。它没有给出要求的确切结果,但那是因为朋友和产品的匹配无论如何都是任意的,所以我强加了自己的排序:

;with OrderedProducts as (
    select Customer,Product,ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY Product) rn
    from @Products
), OrderedFriends as (
    select Customer,Friend,ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY Friend) rn
    from @Friends
)
select
    CASE WHEN COALESCE(op.rn,ofr.rn) = 1 THEN COALESCE(op.Customer,ofr.Customer) END,
    op.Product,
    ofr.Friend
from
    OrderedProducts op
        full outer join
    OrderedFriends ofr
        on
            op.Customer = ofr.Customer and
            op.rn = ofr.rn
order by COALESCE(op.Customer,ofr.Customer),COALESCE(op.rn,ofr.rn)

给出结果:

     Product Friend
---- ------- ------
A    Bike    Andrew
NULL Boat    John
NULL Car     NULL
B    Bar     Baz
NULL Foo     NULL

基本上,由于你似乎没有,我在这两个表之间的两行匹配时制定了我自己的规则 - 行应该在每个客户中按字母顺序编号,然后使用这些行号来创建表之间的唯一匹配。

COALESCE捣乱需要与朋友打交道,没有产品,产品和朋友。 CASE是我唯一可以理解的方式,只有客户名称出现在一行上。


这就是我设置样本数据的方式:

declare @Products table (
    Customer char(1) not null,
    Product varchar(4) not null
)
insert into @Products (Customer , Product) values
(    'A'    ,   'Car'),
(    'A'    ,  'Bike'),
(    'A'    ,  'Boat'),
(    'B'    ,   'Foo'),
(    'B'    ,   'Bar')

declare @Friends table (
    Customer char(1) not null,
    Friend varchar(6) not null
)
insert into @Friends (Customer , Friend) values
(    'A'    ,   'John'),
(    'A'    ,  'Andrew'),
(    'B'    ,   'Baz')

答案 1 :(得分:1)

您需要2个单独的查询,因为您只需要2个表中的数据列表(具有相同的where条件)

您使用的是什么SQL引擎?

答案 2 :(得分:0)

(这是一个很大的评论)

您在问题中提供的结果集有三行:

 Customer   Products    Friends
 ------------------------------
 A        - Car       - John
 <NULL>   - Bike      - Andrew
 <NULL>   - Boat      - <NULL>

由于SQL不是程序性的,而是基于集合,因此在功能上等同于

 Customer   Products    Friends
 ------------------------------
 <NULL>   - Boat      - <NULL>
 <NULL>   - Bike      - Andrew
 A        - Car       - John

这没有意义(对于两个人的例子来说更少)。

您基本上想要的是每个人获得产品列表和汽车列表,并在单个网格中显示。

  • 但是应该如何确定哪个产品“匹配”每个朋友,因为它们将在同一行?
  • 如果朋友列表中间的网格中有分页符,空值会发生什么变化?
  • 如何根据空值对行进行排序?

在这种情况下,如果您只是将数据库中的所有数据都发送到服务器,并使用VB.NET构建GridView的数据源,我认为您会感觉更好。