如何链接以下2个表以获得SQL Server中显示的结果? (续)

时间:2011-02-07 05:46:53

标签: sql-server sql-server-2005

访问

LoginID, StaffName, qno, trackno, tmstamp,    Service
1,       James,     1001, 1,      01-01-2011, No1     (transfer to No2)
2,       John,      1002, 2,      01-01-2011, No1
2,       John,      1003, 3,      01-01-2011, No1
1,       James,     1001, 1,      01-01-2011, No2     (transfered from No1)
2,       James,     1003, 3,      01-01-2011, No1     (recall the queue no)

content, trackno, tmstamp
001,      1,       01-01-2011
002,      1,       01-01-2011
001,      2,       01-01-2011
002,      2,       01-01-2011
003,      2,       01-01-2011
001,      3,       01-01-2011
001,      1,       01-01-2011
001,      3,       01-01-2011
002,      3,       01-01-2011

结果

StaffName, tmstamp,   noOfQno, noOfContent
James,     01-01-2011, 3,       5
John,      01-01-2011, 2,       4

我已经问过这个问题。 (类似于这个问题。)

how to link the following 2 tables to get the result which is shown below in SQL Server?`

正确答案已经存在。

SELECT StaffName, tmstamp, noOfQno, noOfContent
  FROM (
                SELECT StaffName, tmstamp, trackno, COUNT(1) noOfQno
                    FROM Visit
                GROUP BY StaffName, tmstamp, trackno
             ) a LEFT JOIN
             (
                SELECT trackno, COUNT(1) noOfContent
                    FROM Matter 
                GROUP BY    trackno
             ) b
    ON  b.trackno = a.trackno

但根据答案,答案有点不对。

根据答案我得到的结果是......

Result
StaffName, tmstamp,   noOfQno, noOfContent
James,     01-01-2011, 3,       6
John,      01-01-2011, 2,       6

那是因为

对于line 1表格的VisitnoOfContenct应为2,line 4VisitnoOfContent应为1. ,共3个。

但根据答案:对于line 1noOfContent为3,line 4也是3.然后总值变为6.

所以我问如何更新该声明。

P.S。声明不会像结果一样给出总数。相反,它将逐行给出值。

3 个答案:

答案 0 :(得分:1)

试试这个:

我使用您示例中的确切数据创建示例表。基于此我测试您的查询并想出了这个。

第一次查询: SELECT StaffName,tmstamp,trackno,COUNT(1)noOfQno                     来自访问                 GROUP BY StaffName,tmstamp,trackno

StaffName   tmstamp trackno noOfQno
James   01-01-2011  1   2
John    01-01-2011  2   1
John    01-01-2011  3   2

第二次查询: SELECT trackno,COUNT(1)noOfContent                     来自物质                 GROUP BY trackno

trackno noOfContent
1   3
2   3
3   3

加入:

SELECT StaffName, tmstamp, SUM(noOfQno) asnoOfQno ,SUM(noOfContent) as noOfContent
  FROM (
                SELECT StaffName, tmstamp, trackno, COUNT(1) noOfQno
                    FROM Visit
                GROUP BY StaffName, tmstamp, trackno
             ) a LEFT JOIN
             (
                SELECT trackno, COUNT(1) noOfContent
                    FROM Matter 
                GROUP BY    trackno
             ) b
    ON  b.trackno = a.trackno
    group by StaffName, tmstamp

结果:

StaffName   tmstamp noofQno noofContent
James   01-01-2011  2   3
John    01-01-2011  3   6

此致

答案 1 :(得分:1)

你不能用你拥有的表做你想做的事。如果我理解正确,则表示Visit中的第1行链接到Matter中的第1行和第2行,而Visit中的第4行链接到Matter中的第7行,这将使noOfContent等于3。

你必须在表之间链接的唯一字段是trackno,并且使用它将有三行来自Matter,第三行是Visit,第三行是第7行,所以noOfContent是6。

如果在应该链接的行的Visit和Matter中相同,则可以链接字段tmstamp。你必须检查你的实际数据,看看是否是这种情况。

这个问题的正确答案是您需要重新设计表结构并在Visit中识别主键并将其作为外键添加到Matter中。

修改1 由于假设trackno列中的一个值不能被另一个StaffName重用,Crimsonland给出的答案给出了正确的结果。看起来在您的数据中,trackno 1属于John,trackno 2和3属于James。如果是这种情况,该查询将适合您。

编辑2 这是一个版本,我使用tmstamp来确定Matter与Visit之间的关系。我假设Matter.tmstamp大于链接行的Visit.tmstamp,我假设在Visit中一行中最后一行插入的行的tmstamp值小于Visit中的下一个tmstamp值。

declare @Visit table
(
  LoginID int,
  StaffName varchar(50),
  qno int,
  trackno int,
  tmstamp datetime,
  [Service] char(3)
)

declare @Matter table
(
  content int,
  trackno int,
  tmstamp datetime
)

insert into @Visit values (1, 'James', 1001, 1, '2011-01-01 00:00:00', 'No1')
insert into @Visit values (2, 'John',  1002, 2, '2011-01-01 00:00:10', 'No1')
insert into @Visit values (2, 'John',  1003, 3, '2011-01-01 00:00:20', 'No1')
insert into @Visit values (1, 'James', 1001, 1, '2011-01-01 00:00:30', 'No2')
insert into @Visit values (2, 'James', 1003, 3, '2011-01-01 00:00:40', 'No1') 

insert into @Matter values (001, 1, '2011-01-01 00:00:01')
insert into @Matter values (002, 1, '2011-01-01 00:00:02')
insert into @Matter values (001, 2, '2011-01-01 00:00:11')
insert into @Matter values (002, 2, '2011-01-01 00:00:12')
insert into @Matter values (003, 2, '2011-01-01 00:00:13')
insert into @Matter values (001, 3, '2011-01-01 00:00:21')
insert into @Matter values (001, 1, '2011-01-01 00:00:31')
insert into @Matter values (001, 3, '2011-01-01 00:00:41')
insert into @Matter values (002, 3, '2011-01-01 00:00:42')

;with cteVisit
as
(
  select
    StaffName,
    qno,
    trackno,
    tmstamp as VisitStart,
    (select coalesce(min(tmstamp), GetDate())
     from @Visit as V2
     where V2.tmstamp > V1.tmstamp) as VisitStop
  from @Visit as V1
)
select
  V.StaffName,
  max(VisitStart) as tmstamp,
  (select count(*)
   from cteVisit as V2
   where V2.StaffName = V.StaffName) as noOfQno,
  (select count(*)
   from @Matter as M
     inner join cteVisit V3
      on M.tmstamp >= V3.VisitStart and
         M.tmstamp < V3.VisitStop
   where V3.StaffName = V.StaffName) as noOfQno
from cteVisit as V
group by StaffName

结果

StaffName tmstamp                 noOfQno noOfQno
James     2011-01-01 00:00:40.000 3       5
John      2011-01-01 00:00:20.000 2       4

答案 2 :(得分:0)

我不完全确定加入时间戳。

您可以在Nº轨道上离开加入参观Matter并使用CASE WHEN ... ELSE ....结构。像这样的东西(这不是正确的SQL代码)

SELECT StaffName, tmstamp, 
    SUM(CASE WHEN qno IS NOT NULL THEN 1 ELSE 0) AS noOfQno,
    SUM(CASE WHEN content IS NOT NULL THEN 1 ELSE 0) AS noOfContent
  FROM Visit LEFT JOIN Matter
    ON Visit.trackno = Matter.trackno
 GROUP BY StaffName, tmstamp

再次,不是完美的代码!但这是必不可少的想法。

希望它有所帮助!