如何将子查询与其他 table 集成并抓取名称列?

How to integrate subquery with other table and grab name column?

我有搜索应用程序,从 itemregistrationpangkat table:

中找到已按某些标准(类别、经验年限等)过滤的个人信息
 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      

我对最后一个过滤器 'tempoh perkhidmatan by negeri' 有疑问。我需要按州(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);

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

    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,它可以删除重复的行。

我认为它显示重复的原因是因为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 table 有两个 itemRegistrationID 具有不同的 NegeriID 等,SUM(DISTINCT m.duration) 将不起作用。如果我找到更好的方法,让我尝试一下并更新我的答案。

更新: 我在这里创建了一个 fiddle:DB Fiddle