这是我的sql(在mysql表中)
select * from(SELECT sample_register.usin,
DATE_FORMAT(sample_register.doc,'%d-%m-%Y') as doc1,
sample_register.location,
sample_register.description,
sample_register.type,
sample_allocation.gamma,
gamma_results.act,
gamma_results.act_sd,
gamma_results.mdl,
gamma_results.bdl,
DATE_FORMAT(count_dt,'%d-%m-%Y') as count_dt
FROM sample_register
LEFT JOIN sample_allocation
ON sample_register.usin=sample_allocation.usin
LEFT JOIN gamma_results
ON gamma_results.usin = sample_register.usin
AND gamma_results.istp='Cs137'
WHERE mid(sample_register.usin,3,1)='F'
AND sample_register.doc BETWEEN '2015-01-01'
AND '2015-03-31'
AND sample_register.category='ter'
AND sample_allocation.gamma='Y'
ORDER BY mid(sample_register.usin,3,1),
sample_register.doc,
sample_register.usin) AS a
LEFT JOIN (SELECT sample_register.usin,
gamma_results.act,
gamma_results.act_sd,
gamma_results.mdl,
gamma_results.bdl
FROM sample_register
LEFT JOIN gamma_results
ON gamma_results.usin = sample_register.usin
AND gamma_results.istp='k40'
WHERE mid(sample_register.usin,3,1)='F'
AND sample_register.doc
BETWEEN '2015-01-01'
AND '2015-03-31'
AND (sample_register.category='ter')
ORDER BY mid(sample_register.usin,3,1),
sample_register.doc,
sample_register.usin) AS b
ON a.usin=b.usin
gamma_results表中有4条记录。 2015年4月10日和2015年4月18日各有两条记录。
USIN istp act count_dt
-----------------------------------------
15FML002 Cs137 0.00769 10/04/15
15FML002 K40 0 10/04/15
15FML002 Cs137 0.00608 18/04/15
15FML002 K40 12.117 18/04/15
以下列形式查询输出数据(为方便起见,我删除了一些字段)
15FML002 0.00769 Y 10/04/15 00
15FML002 0.00769 Y 10/04/15 12.117
15FML002 0.00608 Y 18/04/15 00
15FML002 0.00608 Y 18/04/15 12.117
但我希望在两个记录中获得输出。就像这样
15FML002 0.00769 Y 10/04/15 00
15FML002 0.00608 Y 18/04/15 12.117
如何重新构建(加入或联合)查询以获得这样的输出? ///于2015年4月30日编辑
我无法创建一个sqlfiddle,因为他们的网站存在一些问题。以下是两个表sample_register和gamma结果的DDL和DML。此时可以忽略sample_allocation表。
CREATE TABLE `sample_register` (
`usin` varchar(11) NOT NULL,
`sample_id` varchar(7) NOT NULL,
`doc` date NOT NULL,
`location` varchar(255) DEFAULT NULL,
`category` varchar(50) DEFAULT NULL,
`type` varchar(255) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
`fwt` decimal(10,2) DEFAULT NULL COMMENT 'This filed contains either fwt in gms or volume in ltr for milk or volume of air for particulate',
`dwt` decimal(10,2) DEFAULT NULL,
`ashwt` decimal(10,2) DEFAULT NULL,
`user` varchar(255) DEFAULT NULL,
`to_dt` date DEFAULT NULL COMMENT 'This is for particulate sample filter removal date',
`wc` decimal(10,2) DEFAULT NULL,
`oc` decimal(10,2) DEFAULT NULL,
`ac` decimal(10,2) DEFAULT NULL,
`status` varchar(1) DEFAULT NULL,
`remarks` varchar(255) DEFAULT NULL,
PRIMARY KEY (`usin`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `sample_register` VALUES ('15FML002', 'NIL', '2015-04-09', 'MALLAPUR', 'ter', 'MILK', 'milk', '2000.00', null, null, '1604015', null, null, null, null, null, null);
DROP TABLE IF EXISTS `gamma_results`;
CREATE TABLE `gamma_results` (
`usin` varchar(255) NOT NULL,
`sysid` varchar(255) NOT NULL,
`count_time` decimal(10,0) DEFAULT NULL,
`geo` varchar(255) DEFAULT NULL,
`vol` decimal(10,2) DEFAULT NULL,
`energy` decimal(10,2) DEFAULT NULL,
`istp` varchar(255) DEFAULT NULL,
`bkg` decimal(10,5) DEFAULT NULL,
`eff` decimal(10,3) DEFAULT NULL,
`sigma` decimal(10,5) DEFAULT NULL,
`ncps` decimal(10,5) DEFAULT NULL,
`sd` decimal(10,5) DEFAULT NULL,
`mdl` decimal(10,5) DEFAULT NULL,
`act` decimal(10,5) DEFAULT NULL,
`act_sd` decimal(10,5) DEFAULT NULL,
`bdl` varchar(1) DEFAULT NULL,
`entry_time` datetime DEFAULT NULL,
`entered_by` int(11) DEFAULT NULL,
`count_dt` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `gamma_results` VALUES ('15FML002', 'HPGE2', '25000', 'nb', '1000.00', '364.48', 'I131', '0.01000', '3.400', '0.00190', '-0.01000', '0.00041', '0.06882', null, '0.00000', 'Y', '2015-04-13 10:24:11', '1619381', '2015-04-10');
INSERT INTO `gamma_results` VALUES ('15FML002', 'HPGE2', '25000', 'nb', '1000.00', '661.66', 'Cs137', '0.00020', '2.060', '0.00027', '-0.00020', '0.00006', '0.00769', null, '0.00000', 'Y', '2015-04-13 10:24:57', '1619381', '2015-04-10');
INSERT INTO `gamma_results` VALUES ('15FML002', 'HPGE2', '25000', 'nb', '1000.00', '1460.73', 'K40', '0.00500', '0.911', '0.00134', '-0.00450', '0.00032', '1.37855', null, '0.00000', 'Y', '2015-04-13 10:25:37', '1619381', '2015-04-10');
INSERT INTO `gamma_results` VALUES ('15FML002', 'HPGE2', '15000', 'nb50', '2000.00', '661.66', 'Cs137', '0.00020', '3.380', '0.00035', '-0.00020', '0.00006', '0.00608', null, '0.00000', 'Y', '2015-04-20 10:21:48', '1619381', '2015-04-18');
INSERT INTO `gamma_results` VALUES ('15FML002', 'HPGE2', '15000', 'nb50', '2000.00', '1460.73', 'K40', '0.00500', '1.550', '0.00173', '0.04008', '0.00176', '0.52302', '12.11700', '0.53200', 'N', '2015-04-20 10:23:00', '1619381', '2015-04-18');
答案 0 :(得分:8)
之前我见过这样的输出。
这是由于连接中的微小错误引起的。如果我没记错的话,我通过将一些连接嵌套为子查询来解决这个问题,所以我将每个表添加到一个连接的现有表中。我可能过度混合但它确实很好用。 (更新:是的,我现在看到的正是你正在做的事情)。
在该混合中的某个时刻,连接并不是唯一的,或者您安排它的方式并不是唯一的,因此SQL为您提供了它可以提供的所有组合。
(当然,假设不仅仅是缺少GROUP BY
令人不安的事情。这就是问题的另一个原因。)
我将仔细查看您的SQL,看看我是否能发现问题,但是一点点试错会更快,更快。
更新1:这可能是一个非常令人印象深刻的黑客或错误,我无法理解它。
LEFT JOIN gamma_results
ON gamma_results.usin = sample_register.usin
AND gamma_results.istp='Cs137'
作为加入的一部分,我从未见过条件。我不能告诉你这是否会起作用,但我的直觉反应是想把它放在WHERE
条款中。你可以随意带我上学,因为你似乎知道自己在做什么,而且我没有动手去实际项目(我也不知道所有事情)。
更新2:鉴于您的硬编码连接必须接近工作,我的感觉是,当您使用聚合函数时,我希望嵌套SELECT中有GROUP by(count
)。
我记得曾经做过一个非常复杂的查询,当你明白它时,它实际上是在为每个table_a添加table_b"。诚实地与GROUP BY
交朋友,如果这不能解决你的问题,那么我就是一只小的无害的猴子。
答案 1 :(得分:4)
首先,如果您需要有关某些特定数据集查询的帮助,则应提供相同的数据和sqlfiddle。
由于我没有关于小提琴的数据,我的猜测是:
SELECT sample_register.usin,
DATE_FORMAT(sample_register.doc,'%d-%m-%Y') as doc1,
sample_register.location,
sample_register.description,
sample_register.type,
sample_allocation.gamma,
gr.act,
gr.act_sd,
gr.mdl,
gr.bdl,
gr.count_dt,
grK40.act
FROM sample_register
INNER JOIN sample_allocation
ON sample_register.usin=sample_allocation.usin
AND sample_allocation.gamma='Y'
LEFT JOIN (
SELECT
usin,
act,
act_sd,
mdl,
bdl,
count_dt,
DATE_FORMAT(count_dt,'%d-%m-%Y') as count_dt_formatted
FROM gamma_results
WHERE istp='Cs137'
) gr
ON gr.usin = sample_register.usin
LEFT JOIN gamma_results grK40
ON grK40.usin = gr.usin
AND grK40.istp='k40'
AND grK40.count_dt = gr.count_dt
WHERE mid(sample_register.usin,3,1)='F'
AND sample_register.doc BETWEEN '2015-01-01' AND '2015-03-31'
AND sample_register.category='ter'
ORDER BY mid(sample_register.usin,3,1),
sample_register.doc,
sample_register.usin
但这只是一个猜测,因为它看起来非常堰。
您写道:
gamma_results表中有4条记录。 2015年4月10日和2015年4月18日各有两条记录:USIN
,istp
,act
,count_dt
,但在您使用的查询中act,act_sd,mdl,bdl,DATE_FORMAT(count_dt,'%d-%m-%Y') as count_dt
所以我们可以假设您还有其他一些列:act_sd,mdl,bdl
。
在你的下面写道:以下列形式查询输出数据(为方便起见,我删除了一些字段)
15FML002 0.00769 Y 10/04/15 00
15FML002 0.00769 Y 10/04/15 12.117
即使删除了某些字段,这里还有哪些字段?
逻辑上是:usin,act
,未知,count_dt
,未知(act
时等于istp='K40'
)。但这是不可能的,因为你的查询请求中没有这样的字段。在我看来,提供的输出是由于其他一些查询得到的,而不是你向我们展示的那个。
但到目前为止,这是我的猜测。如果有任何问题,欢迎您。
答案 2 :(得分:3)
您撰写的每个表都应该有一个PRIMARY KEY
。这是关系数据库中一个至关重要的概念。如果PRIMARY KEY
中有sample_register
,则gamma_results
中没有15FML002 0.00769 Y 10/04/15 00
15FML002 0.00769 Y 10/04/15 12.117
15FML002 0.00608 Y 18/04/15 00
15FML002 0.00608 Y 18/04/15 12.117
。
假设您有以下行:
1 15FML002 0.00769 Y 10/04/15 00
1 15FML002 0.00769 Y 10/04/15 12.117
2 15FML002 0.00608 Y 18/04/15 00
2 15FML002 0.00608 Y 18/04/15 12.117
假设这些实际上是数据库中不同行的重复,分配主键将创建一个新列,使您的数据看起来像这样:
USIN
对于您的示例,这有点过于简单化,考虑到在您的问题内部的解释中,您说明了
对于每个USIN,单个count_dt上的istp有两个不同的值。因此,在每个计数日期,USIN将有两个记录,其中一个用于istp =' k40'另一个是istp = cs137。由于USIN和计数日期很常见,我想将它显示在一行中。然后,如果USIN有多个(比如' n')计数日期,则会有nx2个记录。但我只需要n行。
我知道你了解这些数据是如何组合在一起的,但是如果你能够告诉SQL数据库数据如何以它理解的语言融合在一起,那么你的SQL查询将变得更清洁和更整洁。
了解主键的位置将有助于您更好地逻辑理解表结构。如果您无法分配主键,则表示该表可能需要拆分为块。这个当然可以从一点规范化中受益。
显然,istp
上有一个1:n的关系,这里有很好的代表,但你在USIN
上的关系也是1:2。这不会反映在不同的表中,而是反映在同一个表中,这意味着count_dt
和GROUP BY
的组合在整个表中重复两次时完全相同。
我并不是说您无法使此查询有效。您需要做的就是在底部粘贴PRIMARY KEY
。但是,没有索引可以说你的桌子会非常慢。即使使用索引,它也会比它需要的速度慢!重要的是,没有PRIMARY KEY
你的SQL数据库将会做很多工作而不是远远需要。
如果您将表格拆分为两个,为每个USIN
/ count_dt
对提供新的istp='k40'
,那么请创建另一个表格来解决您的istp=cs137
和{{1在您已经很长的查询中,您只需要编写一行额外的查询,而且可能更多的时间可以节省您大量的查询时间。
而不是SELECT * FROM tableA LEFT JOIN tableB on tableA.USIN=tableB.USIN...
你会写:
SELECT * FROM tableA
LEFT JOIN tableB on tableA.USIN=tableB.USIN
LEFT JOIN tableX on tableB.id = tableX.tableB_id
....
您应该以相同的数据集结束。如果您只想要唯一的值,那么您需要做的就是摆脱第二个JOIN
。
如果由于某种原因您无法更改表格结构,那么您可以选择创建一个由USIN
,count_dt
和istp
组成的复合主键,因为这些应该是唯一的,应该只在表格中显示一次特定的组合。这可以迅速膨胀,但应该给你一般的要点。
要使用此方法创建不同的值,您应该在USIN
和count_dt
上有一个复合索引,然后使用GROUP BY USIN, count_dt
。
答案 3 :(得分:0)
@masoondreamz,我为可能的解决方案创造了一个小提琴。它是 - http://sqlfiddle.com/#!9/5bcae/27/0
解决方案的基本要素是我按Count_DT列中的日期进行分组,并将其添加到子查询的关节条件中。我确实将列数修改为您在示例结果中显示的列表。