ORDER BY then GROUP BY a datetime value - mysql

I have the following MySQL query:
SELECT t.date_time, COUNT(t.submission_id) AS click_count, s.title, s.first_name, s.family_name, s.email, ut.ukip_name, a.advertiser_name
FROM recards.tracking t
INNER JOIN submissions s ON t.submission_id = s.submission_id
INNER JOIN form_settings fs ON t.form_id = fs.form_id
INNER JOIN advertisers a ON t.advertiser_id = a.advertiser_id
INNER JOIN db2829.ukip_titles ut ON fs.ukip_title_id = ut.ukip_title_id
WHERE t.advertiser_id = 621
GROUP BY t.submission_id
ORDER BY t.date_time DESC
However, of course, as the ORDER BY is done after the GROUP BY, I only get the first record, where as I need the last. Investigating, I read about using MAX() on the column during the SELECT, but that does not work with datetime types.
Is there another work around? Maybe embedding SELECTs within SELECTs? What I have above is about as far as my MySQL knowledge goes, unfortunately!

Turns out I was just forgetting the AS after the MAX(), with MAX(t.date_time) AS top_time it works fine.
My full query working:
SELECT MAX(t.date_time) AS top_time, COUNT(t.submission_id) AS click_count, s.title, s.first_name, s.family_name, s.email, ut.ukip_name, a.advertiser_name
FROM recards.tracking t
INNER JOIN submissions s ON t.submission_id = s.submission_id
INNER JOIN form_settings fs ON t.form_id = fs.form_id
INNER JOIN advertisers a ON t.advertiser_id = a.advertiser_id
INNER JOIN db2829.ukip_titles ut ON fs.ukip_title_id = ut.ukip_title_id
WHERE t.advertiser_id = 621
GROUP BY t.submission_id
ORDER BY top_time DESC

You are just grouping by t.submission_id and nothing else, so this query will not work. The other attributes need to be added to the GROUP BY or need to be eliminated from the SELECT.
As far as ordering add MAX(t.date_time) or MIN(t.date_time) to your SELECT and then ORDER BY that result either ascending or descending.

Related

How to access parent column from a subquery within a join

I'm trying to left join the second table useri_ban based on the users' ids, with the extra condition: useri_ban.start_ban = max_start.
In order for me to calculate max_start, I have to run the following subquery:
(SELECT MAX(ub.start_ban) AS max_start, user_id FROM useri_ban ub WHERE ub.user_id = useri.id)
Furthermore, in order to add max_start to every row, I need to inner join this subquery's result into the main result. However, it seems that once I apply that join, the subquery is no longer able to access useri.id.
What am I doing wrong?
SELECT
useri.id as id,
useri.email as email,
useri_ban.warning_type_id as warning_type_id,
useri_ban.type as type,
useri.created_at AS created_at
FROM `useri`
inner join
(SELECT MAX(ub.start_ban) AS max_start, user_id FROM useri_ban ub WHERE ub.user_id = useri.id) `temp`
on `useri`.`id` = `temp`.`user_id`
left join `useri_ban` on `useri_ban`.`user_id` = `useri`.`id` and `useri_ban`.`start_ban` = `max_start`
Does this solve your problem? You need GROUP BY in the inner query instead of another join.
SELECT useri.id, useri.email, maxQuery.maxStartBan
FROM useri
INNER JOIN
(
SELECT useri_ban.user_id ubid, MAX(useri_ban.startban) maxStartBan
FROM useri_ban
GROUP BY useri_ban.user_id
) AS maxQuery
ON maxQuery.ubid = useri.id;

MYSQL Distinct results from a query

What i'm trying to do is get the DISTINCT results using a MYSQL query:
$sql = "SELECT un.*, co.order_product_quantity AS product_num, cu.first_name, cu.surname, cp.product_name, cp.product_thumbnail AS prod_img, co.order_goods_cost, co.order_delivery_cost, co.order_status as status
FROM (
SELECT DISTINCT order_unique_id AS o_id, order_date
FROM cbs_orders
GROUP BY order_unique_id
) un
INNER JOIN cbs_orders co ON co.order_unique_id = un.o_id
INNER JOIN cbs_users cu ON cu.id = co.order_user_id
INNER JOIN cbs_products cp ON cp.product_id = co.order_product_id
ORDER BY un.order_date DESC LIMIT $start_from, $num_rec_per_page ";
I'm looking to get the DISTINCT order_unique_id from the query, i never wrote the query initially, i thought adding "SELECT DISTINCT order_unique_id" would solve the issue but it still brings back duplicate ids.
cheers for any help guys
Graham
You want to leverage GROUP BY correctly; DISTINCT won't help you in this situation. Additional, I'm pretty sure that sub-select is not needed.
Try this
$sql = "SELECT un.order_unique_id AS o_id, un.order_date,
co.order_product_quantity AS product_num,
cu.first_name, cu.surname, cp.product_name,
cp.product_thumbnail AS prod_img, co.order_goods_cost,
co.order_delivery_cost, co.order_status as status
FROM cbs_orders AS un
INNER JOIN cbs_orders co ON co.order_unique_id = un.o_id
INNER JOIN cbs_users cu ON cu.id = co.order_user_id
INNER JOIN cbs_products cp ON cp.product_id = co.order_product_id
GROUP BY un.order_unique_id
ORDER BY un.order_date DESC
LIMIT $start_from, $num_rec_per_page ";
This might produce odd results, because you are not applying aggregate functions to other columns. You may need to use those to get desired results.
Let me hazard a guess that you want records for only the most recent order. If this is the case, then you can do what you want, by properly aggregating the data:
SELECT un.*, co.order_product_quantity AS product_num, cu.first_name,
cu.surname, cp.product_name, cp.product_thumbnail AS prod_img,
co.order_goods_cost, co.order_delivery_cost, co.order_status as status
FROM (SELECT order_unique_id AS o_id, max(order_date) as order_date
FROM cbs_orders
GROUP BY order_unique_id
) un INNER JOIN
cbs_orders co
ON co.order_unique_id = un.o_id INNER JOIN
cbs_users cu
ON cu.id = co.order_user_id INNER JOIN
cbs_products cp
ON cp.product_id = co.order_product_id
ORDER BY un.order_date DESC
LIMIT $start_from, $num_rec_per_page;
If you want only one row per order, then you need to figure out what to do with the products. In my opinion, this interpretation is so different from your current question that you should ask another question, providing sample data and desired results.

MAX() Function not working as expected

I've created sqlfiddle to try and get my head around this http://sqlfiddle.com/#!2/21e72/1
In the query, I have put a max() on the compiled_date column but the recommendation column is still coming through incorrect - I'm assuming that a select statement will need to be inserted on line 3 somehow?
I've tried the examples provided by the commenters below but I think I just need to understand this from a basic query to begin with.
As others have pointed out, the issue is that some of the select columns are neither aggregated nor used in the group by clause. Most DBMSs won't allow this at all, but MySQL is a little relaxed on some of the standards...
So, you need to first find the max(compiled_date) for each case, then find the recommendation that goes with it.
select r.case_number, r.compiled_date, r.recommendation
from reporting r
join (
SELECT case_number, max(compiled_date) as lastDate
from reporting
group by case_number
) s on r.case_number=s.case_number
and r.compiled_date=s.lastDate
Thank you for providing sqlFiddle. But only reporting data is given. we highly appreciate if you give us sample data of whole tables.
Anyway, Could you try this?
SELECT
`case`.number,
staff.staff_name AS ``case` owner`,
client.client_name,
`case`.address,
x.mx_date,
report.recommendation
FROM
`case` INNER JOIN (
SELECT case_number, MAX(compiled_date) as mx_date
FROM report
GROUP BY case_number
) x ON x.case_number = `case`.number
INNER JOIN report ON x.case_number = report.case_number AND report.compiled_date = x.mx_date
INNER JOIN client ON `case`.client_number = client.client_number
INNER JOIN staff ON `case`.staff_number = staff.staff_number
WHERE
`case`.active = 1
AND staff.staff_name = 'bob'
ORDER BY
`case`.number ASC;
Check below query:
SELECT c.number, s.staff_name AS `case owner`, cl.client_name,
c.address, MAX(r.compiled_date), r.recommendation
FROM case c
INNER JOIN (SELECT r.case_number, r.compiled_date, r.recommendation
FROM report r ORDER BY r.case_number, r.compiled_date DESC
) r ON r.case_number = c.number
INNER JOIN client cl ON c.client_number = cl.client_number
INNER JOIN staff s ON c.staff_number = s.staff_number
WHERE c.active = 1 AND s.staff_name = 'bob'
GROUP BY c.number
ORDER BY c.number ASC
SELECT
case.number,
staff.staff_name AS `case owner`,
client.client_name,
case.address,
(select MAX(compiled_date)from report where case_number=case.number),
report.recommendation
FROM
case
INNER JOIN report ON report.case_number = case.number
INNER JOIN client ON case.client_number = client.client_number
INNER JOIN staff ON case.staff_number = staff.staff_number
WHERE
case.active = 1 AND
staff.staff_name = 'bob'
GROUP BY
case.number
ORDER BY
case.number ASC
try this

fetching records with long sql query with multple joins

I will try to explain things as much as I can.
I have following query to fetch records from different tables.
SELECT
p.p_name,
p.id,
cat.cat_name,
p.property_type,
p.p_type,
p.address,
c.client_name,
p.price,
GROUP_CONCAT(pr.price) AS c_price,
pd.land_area,
pd.land_area_rp,
p.tagline,
p.map_location,
r.id,
p.status,
co.country_name,
p.`show`,
u.name,
p.created_date,
p.updated_dt,
o.type_id,
p.furnished,
p.expiry_date
FROM
property p
LEFT OUTER JOIN region AS r
ON p.district_id = r.id
LEFT OUTER JOIN country AS co
ON p.country_id = co.country_id
LEFT OUTER JOIN property_category AS cat
ON p.cat_id = cat.id
LEFT OUTER JOIN property_area_details AS pd
ON p.id = pd.property_id
LEFT OUTER JOIN sc_clients AS c
ON p.client_id = c.client_id
LEFT OUTER JOIN admin AS u
ON p.adminid = u.id
LEFT OUTER JOIN sc_property_orientation_type AS o
ON p.orientation_type = o.type_id
LEFT OUTER JOIN property_amenities_details AS pad
ON p.id = pad.property_id
LEFT OUTER JOIN sc_commercial_property_price AS pr
ON p.id = pr.property_id
WHERE p.id > 0
AND (
p.created_date > DATE_SUB(NOW(), INTERVAL 1 YEAR)
OR p.updated_dt > DATE_SUB(NOW(), INTERVAL 1 YEAR)
)
AND p.p_type = 'sale'
everything works fine if I exclude GROUP_CONCAT(pr.price) AS c_price, from above query. But when I include this it just gives one result. My intention to use group concat above is to fetch comma separated price from table sc_commercial_property_price that matches the property id in this case p.id. If the records for property exist in sc_commercial_property_price then fetch them in comma separated form along with other records. If not it should return blank. What m I doing wrong here?
I will try to explain again if my problem is not clear. Thanks in advance
The GROUP_CONCAT is an aggregation function. When you include it, you are telling SQL that there is an aggregation. Without a GROUP BY, only one row is returns, as in:
select count(*)
from table
The query that you have is acceptable syntax in MySQL but not in any other database. The query does not automatically group by the columns with no functions. Instead, it returns an arbitrary value. You could imagine a function ANY, so you query is:
select any(p.p_name) as p_num, any(p.tagline) as tagline, . . .
To fix this, put all your current variables in a group by clause:
GROUP BY
p.p_name,
p.id,
cat.cat_name,
p.property_type,
p.p_type,
p.address,
c.client_name,
p.price,
pd.land_area,
pd.land_area_rp,
p.tagline,
p.map_location,
r.id,
p.status,
co.country_name,
p.`show`,
u.name,
p.created_date,
p.updated_dt,
o.type_id,
p.furnished,
p.expiry_date
Most people who write SQL think it is good form to include all the group by variables in the group by clause, even though MySQL does not necessarily require this.
Add GROUP BY clause enumerating whatever you intend to have separate rows for. What happens now is that it picks some value for each result column and group_concats every pr.price.

Multiple Joins Mysql Doubles SUM values

Im trying to make a a query, but its doubling the Sum values
SELECT
cidades.id AS id,
cidades.name AS municipio,
Sum(conjuntos.n_uhs) AS uh,
programas.id AS programa,
conjuntos.name
FROM
conjuntos
Inner Join conjuntos_programas ON conjuntos_programas.conjunto_id = conjuntos.id
Inner Join programas ON programas.id = conjuntos_programas.programa_id
Inner Join cidades ON conjuntos.cidade_id = cidades.id
WHERE
conjuntos.situation_id = 2
GROUP BY
conjuntos.cidade_id
ORDER BY
municipio ASC
You've got duplicate rows, you can check this by removing the group by and the SUM(... from your query.
Change the query as follows and tell me if that fixes to problem.
SELECT DISTINCT
cidades.id AS id,
cidades.name AS municipio,
SUM(conjuntos.n_uhs) AS uh,
programas.id AS programa,
conjuntos.name
FROM conjuntos
INNER JOIN conjuntos_programas ON conjuntos_programas.conjunto_id = conjuntos.id
INNER JOIN programas ON programas.id = conjuntos_programas.programa_id
INNER JOIN cidades ON conjuntos.cidade_id = cidades.id
WHERE conjuntos.situation_id = 2
GROUP BY conjuntos.cidade_id
ORDER BY municipio ASC
It sounds like you have a one to many relationship between two or more of your tables to be doing this. Try doing a SELECT * and start debugging your query to see where it is duplicating the rows.