左加入3表

时间:2014-09-04 20:02:44

标签: php mysql sql sql-server database

我有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"; 

3 个答案:

答案 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>';

然后当结果表没问题时,添加计算。