Mysql 创建自反射交叉联接
嗨,我想看看下面的自反射交叉连接是否有其他语法。目标是一种表格的行填充器-每个cdn的日期都应该有条目。我正在使用MySQLMysql 创建自反射交叉联接,mysql,sql,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 le
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
我曾尝试使用简单的别名重新构建交叉连接,但这会导致连接中出现列错误。是否有可能这样做呢?还是应该考虑使用视图?< /P>
由于交叉联接应该只返回两个表的笛卡尔积,因此它应该与只选择两个表而不进行联接相同。但是,以下内容引发了“on子句中的未知列d.labelDate”异常
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
错误代码:1054。“on子句”中的未知列“d.cdn”
因为
d
和n
的长度相对较小,所以查询的大小足够快。我认为您的初衷很接近。。。对于每个日期,您都需要每个网络节点状态的结果。如果在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
阅读评论和额外信息时,您需要一个带有y-
lableDate
和x-cdn
和值的轴心,假设cdn
的值是(a、b、c),并且站点
是一个数字,您可以尝试以下方法:
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
输出应该是这样的(我使用了您提供的示例数据):
在玩了一番之后,这是我能想到的最好的了。表名的参数化似乎是可能的,但会涉及到另一层语句生成,幸运的是,我不需要这个项目
-- --------------------------------------------------------------------------------
-- 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
这可以简单地称为,例如。
呼叫cdn\u pivot('Top100','2013-01-01',2013-02-01')
考虑到测试此代码并将其与任何客户端代码一起保存的相关问题,在客户端生成头部的动态部分是非常诱人的,至少对于这种用例,额外查询的性能损失不应该太高。很明显,关键是理解如何动态生成列。这是非常低效的。。。这样做的目的是什么?要删除未设置日期的条目?我看不出左侧外部联接在做什么。在查询中不使用别名“networks”中的任何内容,但加入它们的位置除外。我也会尽量不做次选择,但也许你需要。如果没有更多的上下文,很难说。@Stephan查询的目的是为每个时间段返回相同数量的行。例如:2013-05可能有
('a','c')
,2013-04可能有('b','c')
。我希望行中有2013-04,'a',NULL
2013-04,'b',5
2013-04,'c',4
2013-05,'a',6
2013-05,'b',NULL
2013-06,'c',7
网络。网站
@MarkBannister感谢你发现了打字错误,因为我太忙了,没有时间检查所有内容。我已更正并添加了错误消息。这似乎表明针对两个表的左连接是不可能的,但如果我将其作为两个单独的左连接来编写,则无法获得所需的结果,并且查询速度明显较慢。谢谢,但这仍然会引发相同的错误。然而,我认为解决方案实际上是生成一个数据透视表,因为这正是我想要的:一个labelDate
bycdn
矩阵,其中站点
或Null
作为值。我认为有必要通过一个有序的结果集,比如我的查询生成的结果集,但事实似乎并非如此。现在我只需要编写创建列的函数。是的,这就是我正在努力的方向。有没有办法创建一个函数/过程来在查询头中生成这些列?我一直在看,但还没有创建一些可以生成并运行查询或只是返回列的东西?您可以从代码端执行。。。使用将生成此查询的脚本。基本上,您需要cdn
字段的不同值来生成pivot。当然,我知道如何在客户端代码中生成查询。我只是想有一个更通用的方法。我想我可以对用户定义的函数做同样的事情?是的,你可以有一个更通用的方法,比如创建一个有输入的方法:field_x(在你的情况下是labelDate)、field_y(在你的情况下是cdn)、field_值(在你的情况下是sites)、table_name(cdn_趋势)。我不确定是否可以使用UDF,但您可以尝试。作为一个简单的函数,它似乎可以很好地工作,但不是作为一个过程。但我怀疑这与不太了解这一切是如何运作的有很大关系。我现在已经成功地协商了所有的OUT
s和IN
s程序,包括GROUP_CONCAT的长度限制
-- --------------------------------------------------------------------------------
-- 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