Using Max in group by - mysql

I have the following query and I want it to generate the result with just the latest date for the category for a store instead of giving out per date transaction:
SELECT c.store,d.node_name category, x.txn_dt, x.txn_tm time, count(c.txn_id) Buyer
FROM pos_swy.5_centerstore_triptype c
join pos_swy.3_txn_itm t on c.txn_id=t.txn_id
join pos_swy.1_upc_node_map d on t.upc_id=d.upc_id
join pos_swy.3_txn_hdr x on t.txn_id=x.txn_id
group by store,txn_dt,node_name;
I tried using max(x.txn_dt) but it really didn't solve the purpose.

you may need the order by ?
SELECT c.store,d.node_name category, max(x.txn_dt) max_date, x.txn_tm time, count(c.txn_id) Buyer
FROM pos_swy.5_centerstore_triptype c
join pos_swy.3_txn_itm t on c.txn_id=t.txn_id
join pos_swy.1_upc_node_map d on t.upc_id=d.upc_id
join pos_swy.3_txn_hdr x on t.txn_id=x.txn_id
group by node_name
order by max_date desc
-- you can change limit 1 to what ever you want to get results

Related

MySql sum DISTINCT after join

I have 2 table that join together ( Orders and Order_item)
When I use join I get duplicates records then I eliminate them with DISTINCT, but when I want to get sum the the shipping_price DISTINCT not works because it just eliminate the same price value and I all my prices are same I get 1 not sum !
If I don't use DISTINCT , I get rows per each items in order
SELECT sum(DISTINCT shipping_price) FROM `product_order`
INNER JOIN `product_address`
ON `product_order`.`address_id` = `product_address`.`id`
INNER JOIN `product_item`
ON `product_order`.`id` = `product_item`.`order_id`
WHERE (`status`<>2)
AND (`company_id`=1968)
AND DATE(date)='2021-08-31'
ORDER BY `product_order`.`id` DESC
how to get sum of shipping price correctly ..
data in order_table is
id shipping_price status
100
200
200
100
sum = 600 , but how to get it, if I did't DISTINCT, I get more than one row per order_items row counts that join tho order..
Use a subquery to get your shipping prices. Something like this:
SELECT product_order.id,
SUM(product_item.price * product_item.quantity) shipping_price
FROM product_order
JOIN product_item ON product_order.id = product_item.order_id
GROUP BY product_order.id
The trick here is to get a subquery that delivers exactly one row per order, with the summed-up shipping priced in it. Do your SUM() ... GROUP BY ...` in the subquery. That way you'll avoid any duplication of items.
TEST THIS before you proceed to make sure it works: giving each order id and its shipping price.
Then use it as if it were a table, JOINing it to the rest.
SELECT total.shipping_price,
product_order.id,
product_address.*
FROM product_order
JOIN product_address
ON product_order.id = product_address.order_id
JOIN (
SELECT product_order.id,
SUM(product_item.price * product_item.quantity) shipping_price
FROM product_order
JOIN product_item ON product_order.id = product_item.order_id
GROUP BY product_order.id
) total ON product_order.id = total.id
ORDER BY product_order.id = total.id
Use a subquery instead of a join.
SELECT (
select sum(shipping_price)
FROM product_item
WHERE po.`id` = `product_item`.`order_id`
) as shipping_price
FROM `product_order` po
INNER JOIN `product_address`
ON `product_order`.`address_id` = `product_address`.`id`
WHERE (`status`<>2)
AND (`company_id`=1968)
AND DATE(date)='2021-08-31'
ORDER BY `product_order`.`id` DESC

How can I eliminate duplicates using MAX function?

I have these tables
recommendation_object_id, exhibitor_name, event_edition_id, timestamp
I want to hide/remove the duplicates in recommendation_object_id to make it a primary key.
I successfully removed most of the dups, but a few recommendation id's have a different event edition id so some id's are still duplicating as a result.
A colleague of mine said I could eliminate those further by using max(timestamp) but I could not pull it off :(
My current query is this:
SELECT DISTINCT r.recommended_object_id, ed.exhibitor_name, sd.event_edition_id, r.object_type, max(r.timestamp)
FROM recommendations r
left join show_details sd on r.event_edition_id = sd.event_edition_id
left join exhibitor_details ed on r.recommended_object_id = ed.exhibitor_id
group by r.recommended_object_id, ed.exhibitor_name, sd.event_edition_id, r.object_type
order by r.recommended_object_id
If you want one row per recommended_object_id, the one with the most recent timestamp, then use window functions:
select r.*
from (select r.recommended_object_id, ed.exhibitor_name, sd.event_edition_id, r.object_type,
row_number() over (partition by recommended_object_id order by r.timestamp desc) as seqnum
from recommendations r left join
show_details sd
on r.event_edition_id = sd.event_edition_id left join
exhibitor_details ed
on r.recommended_object_id = ed.exhibitor_id
) r
where seqnum = 1
order by r.recommended_object_id;

Select most recent record grouped by 3 columns

I am trying to return the price of the most recent record grouped by ItemNum and FeeSched, Customer can be eliminated. I am having trouble understanding how I can do that reasonably.
The issue is that I am joining about 5 tables containing hundreds of thousands of rows to end up with this result set. The initial query takes about a minute to run, and there has been some trouble with timeout errors in the past. Since this will run on a client's workstation, it may run even slower, and I have no access to modify server settings to increase memory / timeouts.
Here is my data:
Customer Price ItemNum FeeSched Date
5 70.75 01202 12 12-06-2017
5 70.80 01202 12 06-07-2016
5 70.80 01202 12 07-21-2017
5 70.80 01202 12 10-26-2016
5 82.63 02144 61 12-06-2017
5 84.46 02144 61 06-07-2016
5 84.46 02144 61 07-21-2017
5 84.46 02144 61 10-26-2016
I don't have access to create temporary tables, or views and there is no such thing as a #variable in C-tree, but in most ways it acts like MySql. I wanted to use something like GROUP BY ItemNum, FeeSched and select MAX(Date). The issue is that unless I put Price into the GROUP BY I get an error.
I could run the query again only selecting ItemNum, FeeSched, Date and then doing an INNER JOIN, but with the query taking a minute to run each time, it seems there is a better way that maybe I don't know.
Here is my query I am running, it isn't really that complicated of a query other than the amount of data it is processing. Final results are about 50,000 rows. I can't share much about the database structure as it is covered under an NDA.
SELECT DISTINCT
CustomerNum,
paid as Price,
ItemNum,
n.pdate as newest
from admin.fullproclog as f
INNER JOIN (
SELECT
id,
itemId,
MAX(TO_CHAR(pdate, 'MM-DD-YYYY')) as pdate
from admin.fullproclog
WHERE pdate > timestampadd(sql_tsi_year, -3, NOW())
group by id, itemId
) as n ON n.id = f.id AND n.itemId = f.itemId AND n.pdate = f.pdate
LEFT join (SELECT itemId AS linkid, ItemNum FROM admin.itemlist) AS codes ON codes.linkid = f.itemId AND ItemNum >0
INNER join (SELECT DISTINCT parent_id,
MAX(ins1.feesched) as CustomerNum
FROM admin.customers AS p
left join admin.feeschedule AS ins1
ON ins1.feescheduleid = p.primfeescheduleid
left join admin.group AS c1
ON c1.insid = ins1.feesched
WHERE status =1
GROUP BY parent_id)
AS ip ON ip.parent_id = f.parent_id
WHERE CustomerNum >0 AND ItemNum >0
UNION ALL
SELECT DISTINCT
CustomerNum,
secpaid as Price,
ItemNum,
n.pdate as newest
from admin.fullproclog as f
INNER JOIN (
SELECT
id,
itemId,
MAX(TO_CHAR(pdate, 'MM-DD-YYYY')) as pdate
from admin.fullproclog
WHERE pdate > timestampadd(sql_tsi_year, -3, NOW())
group by id, itemId
) as n ON n.id = f.id AND n.itemId = f.itemId AND n.pdate = f.pdate
LEFT join (SELECT itemId AS linkid, ItemNum FROM admin.itemlist) AS codes ON codes.linkid = f.itemId AND ItemNum >0
INNER join (SELECT DISTINCT parent_id,
MAX(ins1.feesched) as CustomerNum
FROM admin.customers AS p
left join admin.feeschedule AS ins1
ON ins1.feescheduleid = p.secfeescheduleid
left join admin.group AS c1
ON c1.insid = ins1.feesched
WHERE status =1
GROUP BY parent_id)
AS ip ON ip.parent_id = f.parent_id
WHERE CustomerNum >0 AND ItemNum >0
I feel it quite simple when I'd read the first three paragraphs, but I get a little confused when I've read the whole question.
Whatever you have done to get the data posted above, once you've got the data like that it's easy to retrive "the most recent record grouped by ItemNum and FeeSched".
How to:
Firstly, sort the whole result set by Date DESC.
Secondly, select fields you need from the sorted result set and group by ItemNum, FeeSched without any aggregation methods.
So, the query might be something like this:
SELECT t.Price, t.ItemNum, t.FeeSched, t.Date
FROM (SELECT * FROM table ORDER BY Date DESC) AS t
GROUP BY t.ItemNum, t.FeeSched;
How it works:
When your data is grouped and you select rows without aggregation methods, it will only return you the first row of each group. As you have sorted all rows before grouping, so the first row would exactly be "the most recent record".
Contact me if you got any problems or errors with this approach.
You can also try like this:
Select Price, ItemNum, FeeSched, Date from table where Date IN (Select MAX(Date) from table group by ItemNum, FeeSched,Customer);
Internal sql query return maximum date group by ItemNum and FeeSched and IN statement fetch only the records with maximum date.

Return column value without aggregation for grouped query

Ok, question sound very confusing, I just can't come up with better title.
Here is my query:
SELECT TS.LocationKey, TA.TrailerKey, MAX(TS.ArrivedOnLocal) MaxArrivedOnLocal
FROM dbo.DSPTripStop TS
INNER JOIN dbo.DSPTripAssignment TA ON TS.TripStopKey = TA.ToTripStopKey AND TA.TrailerKey IS NOT NULL
GROUP BY TS.LocationKey, TA.TrailerKey
Query returns list of trailers with locations and last time they were dropped at that location. This is what I need. MAX(time) for location is a goal.
But I'd like to also know which DSPTripStop.TripStopKey this MAX() time happened on.
I can't group by this value. I understand that it is not defined (can be multiple values for the same time). For my purpose ANY random will work. But I can't find any better way then joining second time by MaxArrivedOnLocal to get what I need.
SQL Server already "sees" this data when MAX() aggregated, any way to pull it in this query?
I think this is what you want. Rather than doing a group by, you partition instead, number the rows, then take the top 1
WITH cte AS
(
SELECT TS.LocationKey,
TA.TrailerKey,
TS.ArrivedOnLocal,
TS.TripStopKey,
ROW_NUMBER() OVER (PARTITION BY TS.LocationKey, TA.TrailerKey ORDER BY ArrivedOnLocal DESC) rn
FROM dbo.DSPTripStop TS
INNER JOIN dbo.DSPTripAssignment TA ON TS.TripStopKey = TA.ToTripStopKey AND TA.TrailerKey IS NOT NULL
)
SELECT LocationKey,
TrailerKey,
ArrivedOnLocal,
TripStopKey
FROM cte
WHERE rn = 1
If you need any random value for DSPTripStop.TripStopKey then you can use MAX itself as this will return the latest TripStopKey.
SELECT
TS.LocationKey,
TA.TrailerKey,
MAX(TS.ArrivedOnLocal) MaxArrivedOnLocal,
MAX(TS.TripStopKey)
FROM dbo.DSPTripStop TS
INNER JOIN dbo.DSPTripAssignment TA
ON TS.TripStopKey = TA.ToTripStopKey
AND TA.TrailerKey IS NOT NULL
GROUP BY TS.LocationKey, TA.TrailerKey

MySQL Query: Customer Order Value and Order Count for Multiple Date Ranges

I have the following query that works great for returning the order count and value per customer for the defined period of time.
SELECT
c.company,
c.email,
SUM(o.total_value) AS ttl_order_value,
COUNT(p.order_id) AS ttl_order_count
FROM merch_orders_ist AS o
INNER JOIN contacts_ern AS c
ON (o.contact_id = c.contactid)
INNER JOIN merch_payments_ist AS p
ON (o.id = p.order_id)
WHERE DATE(p.date_of_payment) BETWEEN '2014-01-01' AND '2014-12-31'
GROUP BY c.contactid
ORDER BY ttl_order_value DESC
I need to extend this query to add two more columns that include the order totals and summed value of the orders per customer for a SECOND date range (e.g. 2015 and 2014). The result I'm looking for looks like this...
| company | email | ttl_order_value_2015 | ttl_order_count_2015 | ttl_order_value_2014 | ttl_order_count_2014 |
---------------------------------------------------------------------------------------------------------------
Thank you in advance!
I have given pseudo code which requires some modification but should work based on your requirement.
Note : If syntax is not working then remove SUM(o.total_value) to o.total_value . SUM you can use by writing one simple outer query and group by
SELECT
c.company,
c.email,
-- Using date put some condtions like >,< or extarct year and compare
DECODE(p.date_of_payment, '2014',SUM(o.total_value),0) AS ttl_order_value_2014,
Decode(p.date_of_payment,'2014' ,COUNT(p.order_id),0) AS ttl_order_count_2014,
DECODE(p.date_of_payment, '2015',SUM(o.total_value),0) AS ttl_order_value_2015,
Decode(p.date_of_payment,'2015' ,COUNT(p.order_id),0) AS ttl_order_count_2015,
FROM merch_orders_ist AS o
INNER JOIN contacts_ern AS c
ON (o.contact_id = c.contactid)
INNER JOIN merch_payments_ist AS p
ON (o.id = p.order_id)
WHERE DATE(p.date_of_payment) BETWEEN '2014-01-01' AND '2014-12-31'
GROUP BY c.contactid
ORDER BY ttl_order_value DESC