我有3个不同的表(table1,table2,table3),我需要执行百分比和频率操作并输出HTML表。
表1
CatCodes1 | CatCodes2 | CatCodes3
----------+-----------+----------
75287 | 20220 | 65656
78922 | 20852 | 56666
75287 | 20220 | 62892
78922 | 20852 | 55665
表2:只应拉出测试结果= 1
AllCatCodes | Tested
-------------+---------
75287 | 1
78922 | 0
75287 | 0
78922 | 0
20220 | 1
62892 | 1
20852 | NULL
65656 | 1
表3
CodesCatAll |
------------+
75287 |
56666 |
65656 |
20220 |
我需要输出一个看起来像这样的表
CatCode1(tab1) | % of CatCode(tab1) | Freq in All CatCode(tab2) | Percentage(tab2) | Freq in CodesCatAll(tab3) | Percentage(tab3) |
75287
78922
78992
Total 100% xxx 100% yyy 100%
下面是我为获取catcode1和catCode(table1)的%而编写的代码。问题是如何添加其他两个表和频率。
$sqlCom = "select CatCodes1, CAST(count(*) * 100.0 / sum(count(*)) over()";
$sqlCom .= " AS DECIMAL(18,2)) from table1 group by CatCodes1";
答案 0 :(得分:3)
我相信这会解决问题......您需要将计算作为子查询进行计算,并使用外部查询将所有内容连接在一起。
<强> SQL Fiddle here. 强>
SELECT t1.CatCodes1 AS 'CatCode1(tab1)', t1.myPercent AS '% of CatCode(tab1)',
ISNULL(t2.CountOfAllCatCodes, 0) AS 'Freq in All CatCode(tab2)', ISNULL(t2.myPercent, 0) AS 'Percentage(tab2)',
ISNULL(t3.CountOfCodesCatAll, 0) AS 'Freq in CodesCatAll(tab3)', ISNULL(t3.myPercent, 0) AS 'Percentage(tab3)'
FROM (
SELECT CatCodes1, CAST(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS DECIMAL(18,2)) AS myPercent
FROM table1
GROUP BY CatCodes1
) t1
LEFT OUTER JOIN (
SELECT AllCatCodes, COUNT(*) AS CountOfAllCatCodes, CAST(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS DECIMAL(18,2)) AS myPercent
FROM table2
GROUP BY AllCatCodes
) t2 ON t1.CatCodes1 = t2.AllCatCodes
LEFT OUTER JOIN (
SELECT CodesCatAll, COUNT(*) AS CountOfCodesCatAll, CAST(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS DECIMAL(18,2)) AS myPercent
FROM table3
GROUP BY CodesCatAll
) t3 ON t1.CatCodes1 = t3.CodesCatAll
答案 1 :(得分:3)
我们试试吧。您需要将计算作为子查询进行。此外,您还需要一个内部查询来计算数据集中包含的记录数。然后有一个外部查询将所有内容连接在一起。
<强> Original SQL Fiddle HERE. 强>
的 Updated SQL Fiddle HERE. 强>
的 Third updated SQL Fiddle HERE. 强>
SELECT t1.CatCodes1 AS 'CatCode1(tab1)', t1.myPercent AS '% of CatCode(tab1)',
ISNULL(t2.CountOfAllCatCodes, 0) AS 'Freq in All CatCode(tab2)',
CASE
WHEN ttl.t2Ttl = 0 THEN 0
ELSE CAST(ISNULL(t2.CountOfAllCatCodes, 0) * 100.0/ttl.t2Ttl AS DECIMAL(18,2))
END AS 'Percentage(tab2)',
ISNULL(t3.CountOfCodesCatAll, 0) AS 'Freq in CodesCatAll(tab3)',
CASE
WHEN ttl.t3Ttl = 0 THEN 0
ELSE CAST(ISNULL(t3.CountOfCodesCatAll, 0) * 100.0/ttl.t3Ttl AS DECIMAL(18,2))
END AS 'Percentage(tab3)'
FROM (
SELECT CatCodes1, CAST(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS DECIMAL(18,2)) AS myPercent
FROM table1
GROUP BY CatCodes1
) t1
LEFT OUTER JOIN (
SELECT AllCatCodes, COUNT(*) AS CountOfAllCatCodes, CAST(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS DECIMAL(18,2)) AS myPercent2
FROM table2
WHERE ISNULL(Tested, 0) = 1
GROUP BY AllCatCodes
) t2 ON t1.CatCodes1 = t2.AllCatCodes
LEFT OUTER JOIN (
SELECT CodesCatAll, COUNT(*) AS CountOfCodesCatAll, CAST(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS DECIMAL(18,2)) AS myPercent3
FROM table3
GROUP BY CodesCatAll
) t3 ON t1.CatCodes1 = t3.CodesCatAll
CROSS JOIN (
--Calculate total records which are matched...
SELECT SUM(ISNULL(t2.CountOfAllCatCodes, 0)) as t2Ttl, SUM(ISNULL(t3.CountOfCodesCatAll, 0)) AS t3Ttl
FROM (
SELECT CatCodes1
FROM table1
GROUP BY CatCodes1
) t1
LEFT OUTER JOIN (
SELECT AllCatCodes, COUNT(*) AS CountOfAllCatCodes
FROM table2
WHERE ISNULL(Tested, 0) = 1
GROUP BY AllCatCodes
) t2 ON t1.CatCodes1 = t2.AllCatCodes
LEFT OUTER JOIN (
SELECT CodesCatAll, COUNT(*) AS CountOfCodesCatAll
FROM table3
GROUP BY CodesCatAll
) t3 ON t1.CatCodes1 = t3.CodesCatAll
) ttl
注意:由于某种原因,SQL Fiddle将'Percentage(tab2)'字段计算为零。我检查了代码并且无法找到我的错误,正如您所看到的,“百分比(tab3)”的编写方式完全相同并且正确评估。您还可以看到CountOfAllCatCodes的计算结果为2,而ttl.t2Ttl的结果为4,结果为50%。所以,我不知道。
要填写页面上的xxx和yyy字段,请在构建表时保持运行总计,或分别引用t2Ttl和t3Ttl字段。
编辑:我弄清楚为什么有些百分比会返回零。这是一种假设的铸造问题。请注意,百分比的原始计算如下:
ISNULL(t2.CountOfAllCatCodes, 0)/ttl.t2Ttl * 100.0
因此,INTEGER / INTEGER * DECIMAL - &gt; [TRUNCATED INTEGER] * DECIMAL - &gt; (十进制)。
或者,使用数字:2/4 * 100.0 - &gt; 0 * 100.0 - &gt; 0
通过稍微切换公式,我改变了假定的数据类型:
ISNULL(t2.CountOfAllCatCodes, 0) * 100.0/ttl.t2Ttl
或者,如果我们愿意,我们可以使用公式上的CAST或CONVERT语句使其明确。
回答评论中提出的问题:
如何从表1中停止显示空值?
要解决此问题,无论何时从Table1中选择,都要在SQL测试中为NULL添加WHERE子句。假设你不想在CatCodes1字段上使用NULL值,它将是这样的:
SELECT [whatever]
FROM Table1
WHERE CatCodes1 IS NOT NULL
您能否向我解释一下查询的作用?像case语句一样,交叉连接,我们有4个左外连接。
现在你正在进入基本的SQL理论,这可能超出原始问题的范围,但是这里有:
CASE语句用于根据各种条件评估字段的多种可能性。请参阅CASE声明中的this link for Microsoft's documentation。在这种情况下,我使用CASE语句来防止“除以零”错误。你看,如果分母值EVER有可能为零,我们希望确保在实际执行计算之前通过测试零来防止此错误。如果它可用,我只会使用IF类型语句:如果分母为零,则返回零,否则为分子/分母。由于SQL没有内联IF语句,我们改为使用CASE语句。
CROSS JOIN是您需要非常小心的事情,但在这种情况下是合适的。我可以很容易地计算出每个表中有多少记录与t1.CatCodes1匹配,我可以很容易地计算t2和t3表中存在多少条记录,但是我无法获得准确数量的匹配的记录只要。为了解决这个问题,我做了一个单独的查询,只计算匹配的记录(ttl表)。然后我CROSS JOIN到这个表,以便查询中的每一行都可以访问计算。 ttl表用作分母来计算总匹配记录的百分比。
LEFT OUTER JOIN用于获取一个表中的所有行,并且仅用于获取第二个表中的所有行。老实说,我猜这是否是这种情况下的正确连接。它比INNER JOIN安全一点,因为只要记录存在于我们的主表中,我们就会在数据集中看到结果。但是,如果我们使用INNER JOIN,那么ID将需要存在于ALL THREE表中以便显示在我们的结果中。您可以找到更多info about LEFT OUTER JOINS here...
如果您需要有关SQL正在做什么的其他任何解释,请告诉我......
答案 2 :(得分:0)
浏览此页http://sqlpro.developpez.com/cours/sqlaz/jointures/ 对不起,这是法语,但是阅读包含&#34;加入&#34;的代码。可能会帮助你。
首先,尝试在没有任何计算的情况下提取3个表上的数据。 并显示:
echo '<pre>';
print_r($result);
echo '</pre>';
然后当结果表没问题时,添加计算。