How to code better this multiple select subquery(subqueries)? - mysql

Basically below query now works in order to retrieve what I want.
But I'm pretty sure there is a more efficient way to write this query:
SELECT dg.ultimo_codigo_de_gestion_prejuridico, dg.hora_inicio_gestion,
dg.telefono, dg.fecha_gestion, cg.valor_codigo, cg.contacto
FROM detalle_gestion_con_obligacion
AS dg INNER JOIN codigo_gestion
AS cg ON dg.ultimo_codigo_de_gestion_prejuridico = cg.cod_gestion
WHERE nro_documento = 1234567
AND DATE(fecha_gestion) NOT IN (2018-10-20) AND telefono
IN ((SELECT tel_residencia FROM obligacion WHERE nro_obligacion = 1234567) ,
(SELECT tel_oficina FROM obligacion WHERE nro_obligacion = 1234567),
(SELECT celular FROM obligacion WHERE nro_obligacion = 1234567),
(SELECT tel_residencia1 FROM obligacion WHERE nro_obligacion = 1234567) )
ORDER BY fecha_gestion DESC, hora_inicio_gestion DESC limit 1;
As you might tell, around the IN clause I want to retrieve agreements (detalle_gestion_con_obligacion) where the telephone belongs to that list.
I am looking for a better solution that doesn't need four different SELECT statements.

You can join with obligacion instead of using IN.
SELECT dg.ultimo_codigo_de_gestion_prejuridico, dg.hora_inicio_gestion,
dg.telefono, dg.fecha_gestion, cg.valor_codigo, cg.contacto
FROM detalle_gestion_con_obligacion AS dg
INNER JOIN codigo_gestion AS cg ON dg.ultimo_codigo_de_gestion_prejuridico = cg.cod_gestion
INNER JOIN obligacion AS o ON telefono IN (o.tel_residencia, o.yel_oficina, o.celular, o.tel_residencial)
WHERE nro_documento = 1234567
AND DATE(fecha_gestion) NOT IN (2018-10-20)
ORDER BY fecha_gestion DESC, hora_inicio_gestion DESC
limit 1;

Related

How to use the SELECT clause twice in a sql statement

I want to have a table where I can view today's balance as well as yesterday's balance as two different column. Is there any way I can select from two different dates?
Below is the SQL statement I have tried however I am not able to see the yesterday balance.
(SELECT food.food_id, food.food_name, food.food_chi_name, food.food_category, food.chinesechar, SUM(inventory.tmr_input+inventory.final_balance), SUM(inventory.balance), SUM(inventory.input), SUM(inventory.reject), SUM(inventory.final_balance), SUM(inventory.tmr_input), SUM(inventory.sale), SUM(inventory.theoritical), SUM(inventory.yest_theoritical), SUM(inventory.3PMsale), SUM(inventory.3PMbalance), SUM(inventory.wholesale) FROM inventory INNER JOIN food ON inventory.food_id=food.food_id WHERE food.outlet = 'T11' AND inventory.date = '04/30/2021' GROUP BY food.food_id ORDER BY food.food_id ASC); (SELECT SUM(inventory.balance) as yesterday_balance FROM inventory INNER JOIN food ON inventory.food_id=food.food_id WHERE food.outlet = 'T11' AND inventory.date = '04/29/2021' GROUP BY food.food_id ORDER BY food.food_id ASC);
You can use a subselect for that purpose
And using aliases helps to get a better overview
SELECT
f1.food_id
, f1.food_name
, f1.food_chi_name
, f1.food_category
, f1.chinesechar
, SUM(i1.tmr_input+i1.final_balance)
, SUM(i1.balance)
, SUM(i1.input)
, SUM(i1.reject)
,SUM(i1.final_balance)
, SUM(i1.tmr_input)
, SUM(i1.sale)
, SUM(i1.theoritical)
, SUM(i1.yest_theoritical)
, SUM(i1.`3PMsale`)
, SUM(i1.`3PMbalance`)
, SUM(i1.wholesale)
,(SELECT SUM(i2.balance)
FROM
inventory i2 INNER JOIN food f2 ON i2.food_id=f2.food_id
WHERE f2.outlet = 'T11' AND i2.date = '04/29/2021'
AND f2.food_id = f1.food_id
) as yesterday_balance
FROM
inventory i1
INNER JOIN
food f1 ON i1.food_id=f1.food_id
WHERE
f1.outlet = 'T11'
AND i1.date = '04/30/2021'
GROUP BY f1.food_id
ORDER BY f1.food_id ASC;

MySQL Find Most Recent/Largest Record Per Group by order by

MySQL Find Most Recent/Largest Record Per Group by order by, and how can i minimize / shorten this query and every time it returns the first row value of the group, whereas i like to select the last row value of a group, and sort the values based on ja.id ? I know this is a bad query can anyone suggest or provide me solution to shorten this query . I have used all the necessary Column Indexes in all the tables. How to shorten the query without the use of union all .both the queries in union all are same expect in the where statement.
SELECT
a.previous_status,
a.rejected_status,
a.rejection_reason_text,
a.rejection_reason,
a.rjaId,
a.refer_applied_status,
a.title,
a.playerId,
a.gameId,
a.gamePostDate,
a.game_referal_amount,
a.country,
a.country_name,
a.state,
a.location,
a.state_abb,
a.game_type,
a.appliedId,
a.appliedStatus,
a.admin_review,
a.is_req_referal_check,
a.memberId,
a.appliedEmail,
a.game_id,
a.referred_id,
a.memStateAbb,
a.memState,
a.memZipcode,
a.memCity,
a.memCountryNme,
a.memCountry,
a.appliedMemberName,
a.first_name,
a.primary_contact,
a.last_name,
a.addressbookImage,
a.userImage,
a.last_login,
a.user_experience_year,
a.user_experience_month,
a.current_designation,
a.current_player,
a.appliedDate,
a.addressbook_id,
a.joiningdate,
a.gameStatus,
a.gameReferalAmountType,
a.gameFreezeStatus,
a.gameFreezeMsg,
a.app_assign_back_to_rp_count,
a.applied_source,
a.max_id,
a.gamesApplied,
a.gamesAppliedId,
SUM(a.totalgameApplied) AS totalgameApplied,
a.application_assign_to_rp_status,
a.rpAppliedSource,
a.applied_on
FROM
(
(
SELECT
ja.previous_status,
ja.rejected_status,
ja.rejection_reason_text,
ja.rejection_reason,
rja.id AS rjaId,
rja. STATUS AS refer_applied_status,
jp.title,
jp.user_user_id AS playerId,
jp.id AS gameId,
jp.posted_on AS gamePostDate,
jp.game_referal_amount,
jp.country,
jp.country_name,
jp.state,
jp.location,
jp.state_abb,
jp.game_type,
ja.id AS appliedId,
IFNULL(ja. STATUS, '') AS appliedStatus,
IFNULL(ja.admin_review, '') AS admin_review,
ja.is_req_referal_check,
usr.id AS memberId,
rja.email AS appliedEmail,
rja.game_id,
rja.referred_id,
mem.state_abb AS memStateAbb,
mem.state AS memState,
mem.zipcode AS memZipcode,
mem.city AS memCity,
mem.country_name AS memCountryNme,
mem.country_code AS memCountry,
usc. NAME AS appliedMemberName,
usc.first_name,
IFNULL(
mem.primary_contact,
usc.phone_number
) AS primary_contact,
usc.last_name,
usc.profileimage_path AS addressbookImage,
usr.profile_image AS userImage,
usr.last_login,
mem.user_experience_year,
mem.user_experience_month,
mem.current_designation,
mem.current_player,
rja.create_date AS appliedDate,
rja.addressbook_id,
IFNULL(ja.joining_date, '') AS joiningdate,
jp. STATUS AS gameStatus,
jp.games_referal_amount_type AS gameReferalAmountType,
jp.game_freeze_status AS gameFreezeStatus,
jp.game_freeze_message AS gameFreezeMsg,
ja.app_assign_back_to_rp_count,
ja.applied_source,
MAX(rja.id) AS max_id,
GROUP_CONCAT(
jp.title
ORDER BY
rja.create_date DESC
) AS gamesApplied,
GROUP_CONCAT(DISTINCT(jp.id)) AS gamesAppliedId,
COUNT(DISTINCT(jp.id)) totalgameApplied,
ja.application_assign_to_rp_status,
1 AS rpAppliedSource,
rja.create_date AS applied_on
FROM
(`refer_gameapplied` AS rja)
JOIN `games_post` AS jp ON `jp`.`id` = `rja`.`game_id`
JOIN `user_socialconnections` AS usc ON `rja`.`addressbook_id` = `usc`.`id`
LEFT JOIN `user_user` AS usr ON `usr`.`email` = `rja`.`email`
LEFT JOIN `user_member` AS mem ON `mem`.`user_id` = `usr`.`id`
LEFT JOIN `game_applied` AS ja ON `ja`.`id` = `rja`.`applied_id`
WHERE
`rja`.`referby_id` = '2389'
GROUP BY
`rja`.`email`
)
UNION ALL
(
SELECT
ja.previous_status,
ja.rejected_status,
ja.rejection_reason_text,
ja.rejection_reason,
jr.id AS rjaId,
jrtm. STATUS AS refer_applied_status,
jp.title,
jp.user_user_id AS playerId,
jp.id AS gameId,
jp.posted_on AS gamePostDate,
jp.game_referal_amount,
jp.country,
jp.country_name,
jp.state,
jp.location,
jp.state_abb,
jp.game_type,
ja.id AS appliedId,
IFNULL(ja. STATUS, '') AS appliedStatus,
IFNULL(ja.admin_review, '') AS admin_review,
ja.is_req_referal_check,
usr.id AS memberId,
jrtm.referto_email AS refappliedEmail,
jr.game_id,
jrtm.id,
mem.state_abb AS memStateAbb,
mem.state AS memState,
mem.zipcode AS memZipcode,
mem.city AS memCity,
mem.country_name AS memCountryNme,
mem.country_code AS memCountry,
usc. NAME AS appliedMemberName,
usc.first_name,
IFNULL(
mem.primary_contact,
usc.phone_number
) AS primary_contact,
usc.last_name,
usc.profileimage_path AS addressbookImage,
usr.profile_image AS userImage,
usr.last_login,
mem.user_experience_year,
mem.user_experience_month,
mem.current_designation,
mem.current_player,
jrtm.refer_on AS appliedDate,
jrtm.referto_addressbookid,
IFNULL(ja.joining_date, '') AS joiningdate,
jp. STATUS AS gameStatus,
jp.games_referal_amount_type AS gameReferalAmountType,
jp.game_freeze_status AS gameFreezeStatus,
jp.game_freeze_message AS gameFreezeMsg,
ja.app_assign_back_to_rp_count,
ja.applied_source,
MAX(jrtm.id) AS max_id,
GROUP_CONCAT(
jp.title
ORDER BY
jr.refer_on DESC
) AS gamesApplied,
GROUP_CONCAT(DISTINCT(jp.id)) AS gamesAppliedId,
COUNT(DISTINCT(jp.id)) totalgameApplied,
ja.application_assign_to_rp_status,
2 AS rpAppliedSource,
jrtm.refer_on AS applied_on
FROM
(`game_refer` AS jr)
JOIN `game_refer_to_member` AS jrtm ON `jrtm`.`rid` = `jr`.`id`
JOIN `games_post` AS jp ON `jp`.`id` = `jr`.`game_id`
JOIN `user_socialconnections` AS usc ON `jrtm`.`referto_addressbookid` = `usc`.`id`
LEFT JOIN `user_user` AS usr ON `usr`.`email` = `jrtm`.`referto_email`
LEFT JOIN `user_member` AS mem ON `mem`.`user_id` = `usr`.`id`
LEFT JOIN `game_applied` AS ja ON `ja`.`referred_by` = `jrtm`.`id`
WHERE
`jrtm`.`status` = '1'
AND `jr`.`referby_user_id` = '2389'
AND `jrtm`.`refer_source` NOT IN ('4')
GROUP BY
`jrtm`.`referto_email`
)
) a
GROUP BY
a.appliedEmail
ORDER BY
a.gamesAppliedId DESC
It sounds like a "groupwise-max" problem. I added a tag that you should research.
At least get rid of the columns that are not relevant to the question.
Try tossing the tables other than jrtm and jr to see if the performance problem persists. (I'm thinking that the LEFT JOINs may be red herrings.)
Try with one part of the UNION, then with the other. This may identify which of the two is more of a burden.
Some indexes to add:
rja: (referby_id, create_date)
jrtm: (status, referto_email)
jrtm: (rid, status, referto_email)
jr: (referby_user_id, refer_on)
DISTINCT is not a function. Don't use parents in DISTINCT(jp.id).

SQL Server Error - Msg 116

My query is as follows, and contains a subquery within it:
SELECT
dbo.Lawsuit.LawsuitNUM, dbo.Lawsuit.LawsuitYear,
dbo.Groups.GroupName, dbo.LawsuitType.LawsuitType,
dbo.Courts.CourtName,
(select
LawsuitID, DOJ, NextMeeting, ReceiptNUM, ExportNUM, ExportDate
from
(select
dbo.LawsuitExport.LawsuitID,
dbo.LawsuitExport.DOJ,
dbo.LawsuitExport.NextMeeting,
dbo.LawsuitExport.ReceiptNUM,
dbo.LawsuitExport.ExportNUM,
dbo.LawsuitExport.ExportDate,
row_number() over(partition by dbo.LawsuitExport.LawsuitID
order by dbo.LawsuitExport.ExportDate desc) as rn
from
dbo.LawsuitExport) as T
where
rn = 1)
FROM
dbo.Courts
INNER JOIN
dbo.LawsuitType ON dbo.Courts.CourtID = dbo.LawsuitType.CourtID
INNER JOIN
dbo.Groups ON dbo.LawsuitType.LawsuitTypeID = dbo.Groups.LawsuitTypeID
INNER JOIN
dbo.Lawsuit ON dbo.Groups.GroupID = dbo.Lawsuit.GroupID
INNER JOIN
dbo.LawsuitExport ON dbo.Lawsuit.LawsuitID = dbo.LawsuitExport.LawsuitID
The error I am receiving is:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS
The line
select LawsuitID,DOJ,NextMeeting,ReceiptNUM,ExportNUM,ExportDate doesnt work because you can only have 1 item returned from a sub query when it is trying to be used in another select statement. For example
SELECT X FROM Y GOOD
SELECT X, (SELECT A,B,C FROM FOO) FROM Y NOT GOOD
A,B,C cannot be mapped to 1 single element so that is invalid
If that's what is your intention then consider modifying your query like
SELECT
dbo.Lawsuit.LawsuitNUM, dbo.Lawsuit.LawsuitYear,
dbo.Groups.GroupName, dbo.LawsuitType.LawsuitType,
dbo.Courts.CourtName,XXX.LawsuitID, XXX.DOJ, XXX.NextMeeting, XXX.ReceiptNUM, XXX.ExportNUM, XXX.ExportDate
FROM
dbo.Courts
INNER JOIN
dbo.LawsuitType ON dbo.Courts.CourtID = dbo.LawsuitType.CourtID
INNER JOIN
dbo.Groups ON dbo.LawsuitType.LawsuitTypeID = dbo.Groups.LawsuitTypeID
INNER JOIN
dbo.Lawsuit ON dbo.Groups.GroupID = dbo.Lawsuit.GroupID
INNER JOIN
dbo.LawsuitExport ON dbo.Lawsuit.LawsuitID = dbo.LawsuitExport.LawsuitID
INNER JOIN (select
LawsuitID,
DOJ,
NextMeeting,
ReceiptNUM,
ExportNUM,
ExportDate,
row_number() over(partition by LawsuitID
order by ExportDate desc) as rn
from
dbo.LawsuitExport) XXX ON dbo.Lawsuit.LawsuitID = XXX.LawsuitID
WHERE XXX.rn = 1;

MySQL display only unique rows

I have a query:
SELECT DISTINCT ZDJECIA.Id_ogloszenia, OGLOSZENIA.Opis, TYP_NADWOZIA.Nazwa_nadwozie,
WOJEWODZTWA.Nazwa_wojewodztwo, OGLOSZENIA.Miasto, OGLOSZENIA.Rocznik,
OGLOSZENIA.Cena, OGLOSZENIA.id_model, MARKI.Nazwa_marka, MODELE.Nazwa_model,
ZDJECIA.Zdjecie, SILNIK.Nazwa_silnik, KOLORY.Nazwa_kolor, OGLOSZENIA.Moc,
OGLOSZENIA.Pojemnosc
FROM OGLOSZENIA, MARKI, MODELE, ZDJECIA, WOJEWODZTWA, TYP_NADWOZIA, SILNIK, KOLORY
WHERE OGLOSZENIA.Id_koloru = KOLORY.Id_koloru
AND OGLOSZENIA.Id_silnik = SILNIK.Id_silnik
AND OGLOSZENIA.Id_kategoria = TYP_NADWOZIA.Id_kategoria
AND MODELE.Id_marka = MARKI.Id_marka
AND OGLOSZENIA.Id_model = MODELE.Id_model
AND OGLOSZENIA.Id_ogloszenia = ZDJECIA.Id_ogloszenia
AND OGLOSZENIA.Id_wojewodztwa = WOJEWODZTWA.Id_wojewodztwa
ORDER BY OGLOSZENIA.Id_ogloszenia DESC LIMIT 3;
In table 'OGLOSZENIA' I have one record.
In Table 'ZDJECIA' I have two records.
'ZDJECIA':
Id | Id_ogloszenia | Zdjecie
1 1 test1.jpg
2 1 test2.jpg
My query displays two rows, one with test1.jpg, second with test2.jpg.
I don't know how display only one row with first row in 'ZDJECIA' (only test1.jpg);
You need to specify more carefully what you want.
Judging from your comment that 'there will be many rows in table Ogloszenia but you need to use one record from Zdjecia' (paraphrasing), it sounds as if you want one row from Zdjecia for each ID in Ogloszenia. If that's the case, you need to decide which row is appropriate. For example, it might be the row with the smallest ID value.
Rewriting your original query with JOIN notation (as recommended in a comment), I get:
SELECT DISTINCT Z.Id_ogloszenia, O.Opis, T.Nazwa_nadwozie,
W.Nazwa_wojewodztwo, O.Miasto, O.Rocznik,
O.Cena, O.id_model, I.Nazwa_marka, E.Nazwa_model,
Z.Zdjecie, S.Nazwa_silnik, K.Nazwa_kolor, O.Moc,
O.Pojemnosc
FROM OGLOSZENIA AS O
JOIN MODELE AS E ON O.Id_model = E.Id_model
JOIN MARKI AS I ON E.Id_marka = I.Id_marka
JOIN ZDJECIA AS Z ON O.Id_ogloszenia = Z.Id_ogloszenia
JOIN WOJEWODZTWA AS W ON O.Id_wojewodztwa = W.Id_wojewodztwa
JOIN TYP_NADWOZIA AS T ON O.Id_kategoria = T.Id_kategoria
JOIN SILNIK AS S ON O.Id_silnik = S.Id_silnik
JOIN KOLORY AS K ON O.Id_koloru = K.Id_koloru
ORDER BY O.Id_ogloszenia DESC LIMIT 3;
Now we need to put a modestly complex sub-query in place on the Zdjecia table.
The sub-query needs to find the Z.Zdjecie value corresponding to the minimum ID value for each ID_ogloszenia:
SELECT Z1.ID_ogloszenia, Z1.Zdjecie
FROM Zdjecia AS Z1
JOIN (SELECT Z2.ID_ogloszenia, MIN(Z2.ID) AS ID
FROM Zdjecia AS Z2
GROUP BY Z2.ID_ogloszenia
) AS Z2
So we embed that into the main query:
SELECT DISTINCT Z.Id_ogloszenia, O.Opis, T.Nazwa_nadwozie,
W.Nazwa_wojewodztwo, O.Miasto, O.Rocznik,
O.Cena, O.id_model, I.Nazwa_marka, E.Nazwa_model,
Z.Zdjecie, S.Nazwa_silnik, K.Nazwa_kolor, O.Moc,
O.Pojemnosc
FROM OGLOSZENIA AS O
JOIN MODELE AS E ON O.Id_model = E.Id_model
JOIN MARKI AS I ON E.Id_marka = I.Id_marka
JOIN (SELECT Z1.ID_ogloszenia, Z1.Zdjecie
FROM Zdjecia AS Z1
JOIN (SELECT Z2.ID_ogloszenia, MIN(Z2.ID) AS ID
FROM Zdjecia AS Z2
GROUP BY Z2.ID_ogloszenia
) AS Z2
) AS Z ON O.Id_ogloszenia = Z.Id_ogloszenia
JOIN WOJEWODZTWA AS W ON O.Id_wojewodztwa = W.Id_wojewodztwa
JOIN TYP_NADWOZIA AS T ON O.Id_kategoria = T.Id_kategoria
JOIN SILNIK AS S ON O.Id_silnik = S.Id_silnik
JOIN KOLORY AS K ON O.Id_koloru = K.Id_koloru
ORDER BY O.Id_ogloszenia DESC LIMIT 3;
Since the sub-query returns just one row per ID_ogloszenia, there will only be one row returned in the main query. If you don't like the MIN(), you can use MAX() or any other single-valued aggregate.
Did not know which one is the ID .. took Opis as ID ;)
SELECT OGLOSZENIA.Opis as ID, ZDJECIA.Id_ogloszenia, ZDJECIA.Zdjecie
FROM OGLOSZENIA
LEFT JOIN ZDJECIA ON OGLOSZENIA.Id_ogloszenia = ZDJECIA.Id_ogloszenia
Group by OGLOSZENIA.Id_ogloszenia
ORDER BY OGLOSZENIA.Id_ogloszenia DESC LIMIT 3;
Use LIMIT 1 instead of 3 at the end of your query. This tells MySQL to return only the first result.
Here is a documentation that explains more about LIMIT: http://dev.mysql.com/doc/refman/5.6/en/limit-optimization.html
Good luck.
You need to make your query more precise if you only want 1 row to be returned. This means adding another WHERE condition in your query.
Right now, the query that you're giving it is returning 2 rows. It's returning exactly what you're asking for.
If you set LIMIT = 1, there's no guarantee whether or not you will get test1.jpg returned or test2.jpg returned, since your ORDER BY clause is ordering based on Id_ogloszenia, which is the same for both rows.

Speed up MySQL join to check for duplicates

I'm using the following query to return all duplicate records with the same first and last name. The trick is that the contact_id, has to be in descending order.
The query returns the contacts as expected, but it is just SO SLOW! Takes about 6-8 seconds when checking around 30,000 records.
I have the contact_firstName, contact_lastName, contact_client_id, and contact_id all indexed in the database.
Any ideas what I could do to try and speed this up a bit? Thanks for your help :)
SELECT z.contact_id, z.contact_firstName, z.contact_lastName, RIGHT(z.contact_lastName,1) AS nameNum
FROM (`contacts` x)
JOIN `contacts` z ON `x`.`contact_firstName` = `z`.`contact_firstName`
AND x.contact_lastName = z.contact_lastName
AND x.contact_client_id = ".$ID."
AND z.contact_client_id = ".$ID."
WHERE `x`.`contact_id` < `z`.`contact_id`
GROUP BY `z`.`contact_id`
Not making any promises, but here's an alternative to try:
SELECT c.contact_id, c.contact_firstName, c.contact_lastName, RIGHT(c.contact_lastName,1) AS nameNum
FROM (SELECT contact_firstName, contact_lastName, MIN(contact_id) AS MinID
FROM contacts
WHERE contact_client_id = ".$ID."
GROUP BY contact_firstName, contact_lastName
HAVING COUNT(*) > 1) t
INNER JOIN contacts c
ON t.contact_firstName = c.contact_firstName
AND t.contact_lastName = c.contact_lastName
AND c.contact_client_id = ".$ID."
AND t.MinID <> c.contact_id
SELECT z.contact_id, z.contact_firstName, z.contact_lastName
, RIGHT(z.contact_lastName,1) AS nameNum
FROM `contacts` x
JOIN `contacts` z ON (x.contact_client_id = z.contact_client_id)
WHERE `x`.`contact_id` < `z`.`contact_id`
And x.contact_client_id = '$id'
GROUP BY `z`.`contact_id`
Make sure you have an index on:
- contact_id.
- contact_client_id