【问题标题】:How to integrate subquery with other table and grab name column?如何将子查询与其他表集成并获取名称列?
【发布时间】:2019-04-26 14:19:29
【问题描述】:

我有搜索应用程序,从 itemregistrationpangkat 表中查找已按某些标准(类别、经验年数等)过滤的个人信息:

 itemregistrationpangkatID|itemregistrationID|NegeriID|yeartamatkhidmat|yearmulakhidmat
  --------------------------------------------------------------------------
                1         |        2         |  Kedah  |      2001    |   2002
                2         |        2         |  Kedah  |      2003    |   2007
                3         |        3         | Melaka  |     2008     |   2012
                4         |        3         | Melaka  |     2013     |   2018
                5         |        4         |    KL   |     2000     |   2001


 itemregistrationID   |  name | SectionID     | CategoryID  
  -----------------------------------------------------------
           1          |  Eric |     1         |     2     
           2          |  Tom  |     2         |     4      
           3          | Anne  |     2         |     4     
           4          | Marie |     3         |     2      
           5          | Bill  |     1         |     3      

最后一个过滤器“negeri 的 tempoh perkhidmatan”有问题。我需要按州(negeri)计算工作经验的数量。例如,当在 state(negeri) 'x' 中搜索 5 年的人时,sql 将汇总所选州中每个人的经验年限。

这是按条件进行 SQL 搜索的完整代码:

   $query = DB::table('itemregistrations')
                ->join('sections', 'itemregistrations.SectionID', '=', 'sections.SectionID')
                ->join('categories', 'itemregistrations.CategoryID', '=', 'categories.CategoryID')
                ->join('operasi', 'itemregistrations.OperasiID', '=', 'operasi.OperasiID')
                ->join('negeri', 'itemregistrations.NegeriID', '=', 'negeri.NegeriID')
                ->join('gred', 'itemregistrations.GredID', '=', 'gred.GredID')
                ->where('itemregistrations.statusProID', '=', 1)
                ->select('itemregistrations.name','sections.sectionname', 'categories.categoryname', 'operasi.operasiname', 'itemregistrations.Nobadan', 'itemregistrations.lahir_yy', 'itemregistrations.pdrm_yy', 'gred.namagred', 'itemregistrations.itemRegistrationID', '');

        if($request->input('negeri_lahir') != ''){
            $query->where('itemregistrations.NegeriID', $request->input('negeri_lahir'));
        }

        if($request->input('kategori') != '') {
            $query->where('itemregistrations.CategoryID', $request->input('kategori'));
        }

        if($request->input('pangkat') != '') {
            $query->where('itemregistrations.OperasiID', $request->input('pangkat'));
        }

        if(request('umur')) {
            $query->whereRaw('YEAR(CURDATE()) - lahir_yy >= ?', [request('umur')]);  
        }

        if($request->input('gred') != '') {
            $query->where('itemregistrations.GredID', $request->input('gred'));
        }

        if(request('tempoh')) {
            $query->whereRaw('YEAR(CURDATE()) - pdrm_yy >= ?', [request('tempoh')]);  
        }

        if($request->input('negeri_perkhidmatan') != '') {
            $query->join('itemregistrationpangkat', 'itemregistrationpangkat.itemRegistrationID', '=', 'itemregistrations.itemRegistrationID')
                ->where('itemregistrationpangkat.NegeriID', $request->input('negeri_perkhidmatan'));           
        }

      if(request('tempoh_negeri')) {
            $query->select(DB::raw('m.itemRegistrationID, sum(m.duration)'))
                  ->from(DB::raw('(SELECT itemRegistrationID, NegeriID, yeartamatkhidmat - yearmulakhidmat as duration FROM itemregistrationpangkat) AS m 
                        RIGHT JOIN itemregistrations ON itemregistrations.itemRegistrationID=m.itemRegistrationID'))
                  ->distinct()
                  ->groupBy('m.itemRegistrationID');
      }

   $newitem = $query->get();

   return response::json($newitem);

需要解决的代码是这个(最后一个过滤器):

    if(request('tempoh_negeri')) {
            $query->select(DB::raw('m.itemRegistrationID, sum(m.duration)'))
                  ->from(DB::raw('(SELECT itemRegistrationID, NegeriID, yeartamatkhidmat - yearmulakhidmat as duration FROM itemregistrationpangkat) AS m 
                        RIGHT JOIN itemregistrations ON itemregistrations.itemRegistrationID=m.itemRegistrationID'))
                  ->distinct()
                  ->groupBy('m.itemRegistrationID');
      }

问题是重复的行。 上面的控制台日志显示:

 0:
 itemRegistrationID: 791
 sum(m.duration): 6

假设:

 0:
 itemRegistrationID: 791
 sum(m.duration): 3

distinct() 不适用于 groupby,如果我删除 groupby,它可以删除重复的行。

【问题讨论】:

  • 那么,你解决了吗?
  • 不,重复仍然存在。我需要群比。我不能单独使用 distinct()
  • 如果我看到你最后一个查询,你正在做一个RIGHT JOIN。是否有特殊原因需要RIGHT JOIN?因为你知道它会从连接的右侧返回所有值,对吧?
  • 如果distinct() 被删除了怎么办?它会给出正确的值吗?您可以在SELECT 中使用SUM(DISTINCT m.duration) 吗?
  • 我用表格更新了问题,并删除了 distinct()。我尝试了您的建议,使用 distinct in sum 并且有效!卓见!我不知道在 sum() 中可以使用 distinct。

标签: mysql laravel-5 group-by distinct


【解决方案1】:

我认为它显示重复的原因是因为RIGHT JOIN。我自己测试了相同的条件,下面是我的测试示例:

--Lets say my itemregistrations table look like this:
+----------------------+-------------+------------+
|  itemRegistrationID  |  firstname  |  lastname  |
+----------------------+-------------+------------+
|                   1  |  A          |  B         |
|                   2  |  C          |  D         |
|                   3  |  E          |  F         |
|                   1  |  A          |  A         |
+----------------------+-------------+------------+
-- notice that there are repeated value of = 1 in itemregistrationID

-- And my itemregistrationpangkat table look like this:
+----------------------+------------+--------------------+-------------------+
|  itemRegistrationID  |  NegeriID  |  yeartamatkhidmat  |  yearmulakhidmat  |
+----------------------+------------+--------------------+-------------------+
|                   1  |  J         |  2019-04-26        |  2009-12-01       |
|                   2  |  S         |  2018-12-31        |  1999-08-19       |
|                   3  |  P         |  2017-12-31        |  2001-03-02       |
+----------------------+------------+--------------------+-------------------+

我在上面提取了你的 MySQL 查询,变成了这个:

SELECT m.itemRegistrationID, SUM(m.duration)
FROM 
    (SELECT itemRegistrationID, NegeriID, 
    YEAR(yeartamatkhidmat) - YEAR(yearmulakhidmat) AS duration 
    FROM itemregistrationpangkat) AS m 
RIGHT JOIN itemregistrations 
ON itemregistrations.itemRegistrationID=m.itemRegistrationID  
GROUP BY m.itemRegistrationID;

-- with the query above, my results are as following:
+----------------------+-------------------+
|  itemRegistrationID  |  sum(m.duration)  |
+----------------------+-------------------+
|                   1  |               20  |
|                   2  |               19  |
|                   3  |               16  |
+----------------------+-------------------+

为了查看导致 id=1 重复值的原因,我执行如下查询:

SELECT * FROM 
    (SELECT itemRegistrationID, NegeriID, 
    YEAR(yeartamatkhidmat) - YEAR(yearmulakhidmat) AS duration 
    FROM itemregistrationpangkat) AS m 
RIGHT JOIN itemregistrations ON 
itemregistrations.itemRegistrationID=m.itemRegistrationID;

-- and it shows the following result:
+----------------------+------------+------------+----------------------+-------------+------------+
|  itemRegistrationID  |  NegeriID  |  duration  |  itemRegistrationID  |  firstname  |  lastname  |
+----------------------+------------+------------+----------------------+-------------+------------+
|                   1  |  J         |        10  |                   1  |  A          |  B         |
|                   1  |  J         |        10  |                   1  |  A          |  A         |
|                   2  |  S         |        19  |                   2  |  C          |  D         |
|                   3  |  P         |        16  |                   3  |  E          |  F         |
+----------------------+------------+------------+----------------------+-------------+------------+

当然,通过在您的SELECT 中添加SUM(DISTINCT m.duration),它会删除所有m.duration 重复项。这是我担心的地方。我不认为m.duration 应该是决定重复项的因素,因为你有itemregistrationIDNegeriID 所以它们的组合应该是独一无二的(或者至少是来自其他领域的一些组合,而不是这两个将是唯一的)。我的进一步测试表明,如果itemregistrationpangkat 表有两个itemRegistrationID 和不同的NegeriID 等,SUM(DISTINCT m.duration) 将不起作用。如果我找到更好的方法,让我尝试一下并更新我的答案。

更新: 我在这里创建了一个小提琴:DB Fiddle

【讨论】:

  • 非常感谢您的回答和解释。你的解释很好,可以理解。我接受了你的回答。
  • 如果您可以查看上述相关问题,那就太好了。谢谢。stackoverflow.com/questions/55860103/…
  • 不客气@joun .. 但正如我在最后一段中解释的那样,我认为还有一些工作要做才能让您获得最准确的结果。如果查询有问题,请测试所有可能的条件并更新我,或者希望这可以帮助您找到获得正确结果的方法。
  • 好的,谢谢你的提醒。我会用更多的数据对它们进行测试,以检查查询是否准确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-26
  • 1970-01-01
  • 2019-09-15
  • 1970-01-01
  • 2022-01-25
相关资源
最近更新 更多