创建自反性交叉连接

时间:2013-05-15 09:35:06

标签: mysql sql

您好我正在寻找以下自我反身交叉连接的替代语法。目标是一种表格的行填充 - 日期应该包含每个cdn的条目。我正在使用MySQL

select 
  d.labelDate, 
  n.cdn,
  networks.sites
from (
  select 
    distinct labelDate 
  from 
    cdn_trend
) as d
cross join (
  select 
    distinct cdn 
  from cdn_trend
) as n
left join cdn_trend as networks 
  on  networks.labelDate = d.labelDate
  and networks.cdn = n.cdn    
order by 
  labelDate, 
  cdn

我尝试使用简单别名重新构建交叉连接,但这会在连接中出现列错误。是可以这样做还是我应该考虑使用视图呢?

因为交叉连接应该简单地返回两个表的笛卡尔积,它应该与没有连接时简单地选择它们相同。但是,以下内容引发了“未知列d.labelDate in on clause”异常

select distinct d.labelDate, n.cdn, networks.sites
from 
cdn_trend as d,
cdn_trend as n
left join cdn_trend as networks ON
(n.labelDate = networks.labelDate
and d.cdn = networks.cdn)
order by labelDate, cdn

Error Code: 1054. Unknown column 'd.cdn' in 'on clause'

由于dn的长度相对较小,因此查询的大小足够快。

3 个答案:

答案 0 :(得分:0)

我认为你的原意很接近......对于每个日期,你都需要每个网络节点状态的结果。如果在没有连接条件的WHERE子句中列出多个表,默认情况下它将创建一个笛卡尔...从中,加入到您的详细信息表......

select 
      d.labelDate, 
      n.cdn,
      networks.sites
   from 
      ( select d.LabelDate, n.cdn
           from 
              ( select distinct labelDate 
                   from cdn_trend ) as d,
              ( select distinct cdn 
                   from cdn_trend ) as n ) as CrossResults
         LEFT JOIN cdn_trend as networks 
         on  CrossResults.labelDate = networks.labelDate
         and CrossResults.cdn = networks.cdn
   order by 
      networks.labelDate, 
      networks.cdn

答案 1 :(得分:0)

根据lableDate和x - cdn以及值sites,假设cdn的值为(a),请阅读评论和额外信息,您需要使用y - sites和x - SELECT labelDate, SUM(IF(cdn = 'a',sites,0)) as cdn_a, SUM(IF(cdn = 'b',sites,0)) as cdn_b, SUM(IF(cdn = 'c',sites,0)) as cdn_c FROM cdn_trend GROUP BY labelDate 和值labelDate cdn_a cdn_b cdn_c 2013-04 NULL 5 4 2013-05 6 NULL NULL .... ,b,c)并且{{1}}是一个可以尝试的数字:

{{1}}

输出应该是这样的(我使用了你的样本数据):

{{1}}

答案 2 :(得分:0)

经过一番游戏,这是我能想到的最好的。似乎可以对表名进行参数化,但是会涉及另一层语句生成,幸运的是,这个项目并不需要。

-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$

CREATE DEFINER="root"@"localhost" PROCEDURE "cdn_pivot"(
    IN slice varchar(64),
    IN start date,
    IN stop date)

BEGIN

SET @@group_concat_max_len = 32000;
SET @sql = NULL;

SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
    ' sum(IF(cdn = ''',
        cdn,
        ''', sites,NULL)) "'
        ,cdn, '"'
    )
  ) INTO @sql
FROM cdns ORDER BY sites;

SET @stmt = CONCAT('SELECT labelDate, ',
@sql,
' from cdns 
WHERE slice = ''',
slice,
''' AND ( labelDate between''',
start,
''' AND ''',
stop,
'''
) 
GROUP BY labelDate');

prepare stmt from @stmt;
execute stmt;
deallocate prepare stmt;

SET @@group_concat_max_len = 1024;
END

这可以简单地称为e。,g。 call cdn_pivot('Top100', '2013-01-01', 2013-02-01')

考虑到与测试此代码并将其保留在任何客户端代码相关的问题,在客户端生成头部的动态部分非常诱人,至少对于这种用例,性能损失是额外的查询不应该太高。关键是显然要了解如何动态生成列。