如何将子查询与其他表和获取名称列集成?

时间:2019-04-25 08:26:28

标签: mysql laravel-5 group-by distinct

我搜索了应用程序,找到了从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)计算工作经验的数量。例如,当搜索州(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,它可以删除重复的行。

1 个答案:

答案 0 :(得分: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         |
+----------------------+------------+------------+----------------------+-------------+------------+

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

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