Not able to use GROUP BY with join query in MySQL - mysql

I need to execute the below Query but not able to do it.
SELECT *
FROM (SELECT *
FROM rider_status
order by created_date DESC) as riderActice
INNER JOIN rider_user ON rider_userId = rider_user.id
Where rider_user.isActive = 1
AND online_status = 1
GROUP by rider_userId
Error: "#1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'riderActice.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by"
I have read some blogs and found the below solution.
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
But Yet executing above solution I am getting another issue which is
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
Please let me know if I am missing something or doing it wrong

You can not select all(* means all) columns from a table and do a group by one column. That is why you are getting an error. If the column is in the select clause and it is not a part of aggregate function then it has to be in a group by clause.
Also, use the aliases you have created riderActice when joining two tables(subquery and a table).
Here is a small demo demonstrating first part of my answer.
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=b10244e667e59bffb146170014dc69ba
If you want to select all columns then do it like this:
SELECT riderActice.rider_userId
, riderActice.created_date
, rider_user.id
, rider_user.isActive
, rider_user.online_status
FROM rider_status as riderActice
INNER JOIN rider_user ON riderActice.rider_userId = rider_user.id
WHERE rider_user.isActive = 1
AND rider_user.online_status = 1
GROUP BY riderActice.rider_userId
, riderActice.created_date
, rider_user.id
, rider_user.isActive
, rider_user.online_status
If you do not want to group by every column then explain to us what is it that you need, but this is the answer to your question.

Related

MySQL Correlated sub query table name out of scope

This form of my correlated sub query comes up with the error message "Unknown column 'Invoices.TranDate' in 'where clause'"
select InvoiceID, TranDate
, ifnull(TotPayments,0) TotPayments, ifnull(CountPayments,0) CountPayments
from Invoices
left join (select DebtorID, sum(TranAmount) TotPayments, count(*) CountPayments
from CashTrans
where CashTrans.TranDate >= Invoices.TranDate
group by DebtorID) PY on PY.DebtorID = Invoices.DebtorID
Yet this version works
select InvoiceID, TranDate
, (select sum(TranAmount) from CashTrans
where CashTrans.TranDate >= Invoices.TranDate
and CashTrans.DebtorID = Invoices.DebtorID) TotPayments
, (select count(*) from CashTrans
where CashTrans.TranDate >= Invoices.TranDate
and CashTrans.DebtorID = Invoices.DebtorID) CountPayments
from Invoices;
What is wrong with the first query? The only thing I can think of is that on my Windows system I have configured lower_case_table_names=2 as I want to preserve mixed case names. Perhaps that has something to do with the first query not seeing Invoice.TranDate in scope? MySQL Documentation and internet searches have not thrown any light on the matter.
https://dev.mysql.com/doc/refman/8.0/en/lateral-derived-tables.html says:
A derived table cannot normally refer to (depend on) columns of preceding tables in the same FROM clause. As of MySQL 8.0.14, a derived table may be defined as a lateral derived table to specify that such references are permitted.
In SQL:1999, the query becomes legal if the derived tables are preceded by the LATERAL keyword (which means “this derived table depends on previous tables on its left side”):
I have not tested it, but I believe your query could be written this way:
SELECT InvoiceID, TranDate,
IFNULL(TotPayments,0) AS TotPayments,
ifnull(CountPayments,0) AS CountPayments
FROM Invoices
LEFT JOIN LATERAL (
SELECT DebtorID,
SUM(TranAmount) AS TotPayments,
COUNT(*) AS CountPayments
FROM CashTrans
WHERE CashTrans.TranDate >= Invoices.TranDate
GROUP BY DebtorID
) AS PY ON PY.DebtorID = Invoices.DebtorID;
Also be aware this requires you to use at least MySQL 8.0.14.

MySQL - inner join on select query error 1052

Im trying to do a select query on a table along with an inner join afterwards to link data from the owner to the cats
the ownercat is using a foreign key on the id linking to the ownerinfo id
USE CATTERY;
SELECT
OWNERINFO.ID, OWNERINFO.First_Name, OWNERINFO.Last_Name, OWNERINFO.Phone, OWNERINFO.AddrL1, OWNERINFO.AddrL2, OWNERINFO.AddrL3, OWNERINFO.PostCode,
GROUP_CONCAT(DISTINCT OWNERCAT.Chip_ID)
FROM OWNERINFO
INNER JOIN OWNERCAT ON OWNERINFO.ID = OWNERCAT.ID
WHERE ID = 1;
I get returned the following error:
Error Code: 1052. Column 'ID' in where clause is ambiguous 0.0014 sec
removing the concat distinct statement still produces the same error, im not sure how to get around this issue
You need to define from which table the ID on WHERE-clause come from (you can use aliases). Secondly, as you are using GROUP_CONCAT, you should have GROUP BY in the query:
SELECT
oi.ID,
oi.First_Name,
oi.Last_Name,
oi.Phone,
oi.AddrL1,
oi.AddrL2,
oi.AddrL3,
oi.PostCode,
GROUP_CONCAT(DISTINCT oc.Chip_ID)
FROM OWNERINFO oi
INNER JOIN OWNERCAT oc ON oc.ID=oi.ID
WHERE oi.ID = 1
GROUP BY oi.ID
The problem is in the WHERE clause: ID is ambiguous, because that column is available in both tables.
You may think that, since you are joining the tables on ID, the database is able to tell that it has the same value, but that's not actually the case.
So just qualify the column in the WHERE clause, ie change this:
WHERE ID = 1
To either:
WHERE OWNERINFO.ID = 1
Or the equivalent:
WHERE OWNERCAT.ID = 1
Also please note that your query uses GROUP_CONCAT(), which is an aggregate function. This implies that you need a GROUP BY clause, that should list all non-aggregated column (ie all columns other than the one that is within GROUP_CONCAT()).

SQL - Nested query optimization

How can I optimize this query SQL?
CREATE TABLE table1 AS
SELECT * FROM temp
WHERE Birth_Place IN
(SELECT c.DES_COM
FROM tableCom AS c
WHERE c.COD_PROV IS NULL)
ORDER BY Cod, Birth_Date
I think that the problem is the IN clause
First of all it's not quite valid SQL, since you are selecting and sorting by columns that are not part of the group. What you want to do is called "select top N in group", check out Select first row in each GROUP BY group?
Your query doesn't make sense, because you have SELECT * with GROUP BY. Ignoring that, I would recommend writing the query as:
SELECT t.*
FROM temp t
WHERE EXISTS (SELECT 1
FROM tableCom c
WHERE t.Birth_Place = c.DES_COM AND
c.COD_PROV IS NULL
)
ORDER BY Cod, Birth_Date;
For this, I recommend an index on tableCom(desc_com, cod_prov). Your database might also be able to use an an index on temp(cod, birth_date, birthplace).

How to update columns in another table from a select query?

i want to update some columns in another table from a query result. I keep getting error. Please help.
Update customer_info
set customer_info.reader_ID = aisle_info.reader_ID,
customer_info.tag_no = tag_logs.tag_no,
customer_info.area = aisle_info.area,
customer_info.max_timestamp = TIMESTAMPDIFF(SECOND,MIN(tag_logs.timestamp),MAX(tag_logs.timestamp))
FROM tag_logs
INNER join aisle_info ON tag_logs.reader_ID = aisle_info.reader_ID
WHERE T.tag_no = 515988190124;
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM tag_logs
INNER join aisle_info ON tag_logs.reader_ID = aisle_info.reader_I' at line 5
You were close. Different databases have slightly different syntax on updates from select/join. Think of MySQL as a select statement, and use the alias of the primary table you are trying to update and then the SET clauses are after that.
So I first will start by writing the SELECT query by itself.
select
CI.Tag_No,
AI.Reader_ID,
AI.Area,
MIN( TL.TimeStamp ) MinTime,
MAX( TL.TimeStamp ) MaxTime
from
customer_info CI
join tag_logs TL
CI.tag_no = TL.tag_no
join aisle_info AI
on TL.Reader_ID = Reader_ID
WHERE
CI.tag_no = 515988190124
group by
CI.Tag_No,
AI.Reader_ID,
AI.Area
So this gives us the final results of what you want, and you can confirm it as needed.
Then apply your update such as
update Customer_Info CIUpd
JOIN
( select
CI.Tag_No,
AI.Reader_ID,
AI.Area,
MIN( TL.TimeStamp ) MinTime,
MAX( TL.TimeStamp ) MaxTime
from
customer_info CI
join tag_logs TL
CI.tag_no = TL.tag_no
join aisle_info AI
on TL.Reader_ID = Reader_ID
WHERE
-- notice your filter is HERE for the one tag_no you want to update
-- and will result with only this on TAG_NO set of values returned
CI.tag_no = 515988190124
group by
CI.Tag_No,
AI.Reader_ID,
AI.Area ) FirstQuery
-- the JOIN will ensure updating only on that one tag_no
ON CIUpd.Tag_No = FirstQuery.Tag_No
set
CIUpd.Reader_ID = FirstQuery.Reader_ID,
CIUpd.Area = FirstQuery.Area,
CIUpd.Max_TimeStamp = TimeStampDiff( second, FirstQuery.MinTime, FirstQuery.MaxTime )
Now this is not a perfect answer as your original query was not a proper query using the MIN() / MAX() context. When doing an aggregate query, you need to apply a group by on all NON aggregate columns. In this case you did not clarify any such group consideration on the Reader_ID and Area which COULD result in multiple rows from your tag_logs and aisle_info tables.
If the aisle info will be the same all the time for a given Tag_No, then that's simple, just skip the grouping on that and change those column retrieve values as MAX() each. if they never change, MAX() or even MIN() will always return the same value and not have an issue with the aggregate query without non-aggregate columns.
If you can provide additional clarification of data, purpose, etc, please edit your original post vs just leaving a comment. Then leave a comment for me to please review with updated info.

DISTINCT with as clause

$query="SELECT a.pk_i_id,a.i_price,b.s_title,c.pk_i_id AS img_id,c.s_extension,d.s_city,d.s_city_area from zl_t_item a, zl_t_item_description b, zl_t_item_resource c, zl_t_item_location d where a.fk_i_category_id=$cat_id and a.pk_i_id=b.fk_i_item_id and a.pk_i_id=c.fk_i_item_id and a.pk_i_id=d.fk_i_item_id ORDER BY a.dt_pub_date DESC";
In this above query i need to add DISTINCT before this c.pk_i_id AS img_id ??
it shows error when i did like below
$query="SELECT a.pk_i_id,a.i_price,b.s_title,DISTINCT c.pk_i_id AS img_id,c.s_extension,d.s_city,d.s_city_area from zl_t_item a, zl_t_item_description b, zl_t_item_resource c, zl_t_item_location d where a.fk_i_category_id=$cat_id and a.pk_i_id=b.fk_i_item_id and a.pk_i_id=c.fk_i_item_id and a.pk_i_id=d.fk_i_item_id ORDER BY a.dt_pub_date DESC";
what is the problem on it?.
It is invalid use of DISTINCT keyword. You can only apply it on a set of columns and not for a specific column skipping other columns
DISTINCT should be applied right after SELECT for a column or set of columns you cannot use DISTINCT between the columns
SELECT DISTINCT c.pk_i_id AS img_id,
a.pk_i_id,a.i_price,b.s_title,c.s_extension,d.s_city,d.s_city_area
from zl_t_item a, zl_t_item_description b, zl_t_item_resource c,
zl_t_item_location d where a.fk_i_category_id=$cat_id
and a.pk_i_id=b.fk_i_item_id and a.pk_i_id=c.fk_i_item_id
and a.pk_i_id=d.fk_i_item_id ORDER BY a.dt_pub_date DESC
In general, using DISTINCT is performance kill.
DISTINCT is actually a filter to remove duplicates.
So, while selecting multiple columns the DISTINCT clause should be applied to the complete set rather than a single column.
Hence you are seeing an error.
The query can be rewritten based on the requirements. If you want filter out duplicates then either you can apply row rank, or group by and having clause to achieve the intended results.
DISTINCT always works on all columns, you might must put it directly after SELECT.
In MySQL there's an easy way to get only one row per img_id, add a GROUP BY img_id
SELECT
a.pk_i_id
,a.i_price
,b.s_title
,c.pk_i_id AS img_id
,c.s_extension
,d.s_city
,d.s_city_area
from
zl_t_item a
,zl_t_item_description b
,zl_t_item_resource c
,zl_t_item_location d
where
a.fk_i_category_id = $cat_id
and a.pk_i_id = b.fk_i_item_id
and a.pk_i_id = c.fk_i_item_id
and a.pk_i_id = d.fk_i_item_id
GROUP BY img_id
ORDER BY
a.dt_pub_date DESC
Of course this is a proprietary MySQL syntax which breaks all the rules of relational dabatabses and will not work with any other RDBMS.
You can have either SELECT DISTINCT <columns> or SELECT <columns> (which actually defaults to SELECT ALL <columns>.) You can't apply DISTINCT to a specific column.
So, the:
SELECT a.pk_i_id ,a.i_price, b.s_title, DISTINCT c.pk_i_id ...
is invalid SQL.