Как интегрировать подзапрос с другой таблицей и захватить имя столбца? - PullRequest
0 голосов
/ 25 апреля 2019

У меня был поиск приложения, поиск личной информации, которая была отфильтрована по некоторым критериям (категории, годам опыта и т. Д.) Из таблицы 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      

У меня была проблема с последним фильтром 'tempoh perkhidmatanпо негери.Мне нужно рассчитать количество опыта работы по штатам (негери).Например, при поиске людей в возрасте 5 лет в штате (negeri) 'x', 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

Функция Different () не работает с groupby, если я удаляю groupby, он может удалять дублирующиеся строки.

1 Ответ

1 голос
/ 26 апреля 2019

Я думаю, что причина, по которой он показывает дублирование, заключается в 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 должен быть фактором при выборе дубликатов, потому что у вас есть itemregistrationID и NegeriID, поэтому комбинация этого должна быть чем-то уникальным (или, по крайней мере, какая-то комбинация из других полей, кроме тех двух, которые будут уникальными).Мои дальнейшие тесты показывают, что если в таблице itemregistrationpangkat есть два itemRegistrationID с разными NegeriID и т. Д., SUM(DISTINCT m.duration) не будет работать.Позвольте мне попробовать и обновить мой ответ, если я нашел лучший способ.

ОБНОВЛЕНИЕ: Я создал скрипку здесь: DB Fiddle

...