Most frequent value + number of time displayed in columns for each - mysql

I've got the following order table:
Client_name|Product Megane|#768_Samsung Megane|#310_Apple
Megane|#659_Samsung Victor|#890_Apple
I'd like to see for each client what's their most bought brand + the number of time they bought it.
So for this table, I'd like this result:
Client_Name|Favourite_brand|Order_number Megan|Samsung|2
Victor|Apple|1
So far this is the query I've built:
SELECT Client_name, brand
FROM (SELECT Client_name, brand, ROW_NUMBER() OVER (PARTITION BY Client_name ORDER BY freq DESC) AS rn
FROM ( SELECT Client_name, brand, COUNT('x') AS freq
FROM (SELECT Client_name, substring(Product,5) as brand
FROM Orders
GROUP BY Client_name, brand) frequency) ranked) client
WHERE rn = 1;
I am still struggling with removing the number before the brand name (ie #768 for instance) by using substring. I shows me an error message
-ERROR: column "frequency.Client_name" must appear in the GROUP BY clause or be used in an aggregate function
So I haven't started yet to think how to add the Order_number column
Your help is highly appreciated!

I think you just have your group by clause in the wrong spot. Try moving it to after the 'frequency' but before the ')'
SELECT Client_name, brand
FROM (SELECT Client_name, brand, ROW_NUMBER() OVER (PARTITION BY Client_name ORDER BY freq DESC) AS rn
FROM ( SELECT Client_name, brand, COUNT('x') AS freq
FROM (SELECT Client_name, substring(Product,5) as brand
FROM Orders) frequency GROUP BY Client_name, brand) ranked) client
WHERE rn = 1;

Related

Output the total amount spent by the customer and the item on which he/she spent the most

There is a table like this, how can I get customer_id, amount_spent, top_item out of it?
amount_spent the amount spent on all items by this customer
top_item, which displays the name of the item for which the customer has spent the most money
I have tried the following query, however I cannot output the top_1 item with it
select customer_id, sum(item_number * item_price) as amount_spent_1m
from temp
group by customer_id
Check the demo here.
You can achieve it as below :
select customer_id, sum(item_number * item_price) as amount_spent_1m,
item_name as top_item_1m
from temp
group by customer_id, item_name
order by amount_spent_1m desc;
It gives me the following result :
I am sure there is a way to do this with one less step but my brain is not seeing it right now -
SELECT customer_id, amount_spent, item_name AS top_item
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY item_total DESC) rn,
SUM(item_total) OVER (PARTITION BY customer_id) amount_spent
FROM (
SELECT customer_id, item_id, item_name, SUM(item_price * item_number) item_total
FROM table1
GROUP BY customer_id, item_id, item_name
) t1
) t2
WHERE rn = 1
db<>fiddle

I need to get last created eligible rider ids and pinged rider ids accordeing to a orderId using a sql query

I need to get my data set as this table
I am trying to get eligible set like this, need to group_concat pinged set also
x.id IN (SELECT MAX(x.id) FROM x WHERE ping rider id IS NULL GROUP BY orderId)
You can assign a group based on the cumulative number of non-null values in eligible_riders. Then aggregate and take the last value:
select og.*
from (select order_id, grp, max(eligible_riders) as eligible_riders,
group_concat(rider_id) as riders,
row_number() over (partition by order_id order by min(id) desc) as seqnum
from (select t.*,
sum(eligible_riders <> '') over (partition by order_id order by id) as grp
from t
) t
group by order_id, grp
) og
where seqnum = 1;
Hmmm . . . You could also do this with a correlated subquery, which might look a bit simpler:
select order_id, max(eligible_riders) as eligible_riders,
group_concat(rider_id) as riders
from t
where t.id >= (select max(t2.id)
from t t2
where t2.order_id = t.order_id and
t2.eligible_riders <> ''
)
group by order_id;
For performance, you want an index on (order_id, eligible_riders).

Get the last record from each month, from each MATERIAL id after a rolling sum

I have a table which I need to perform a rolling sum for each material. I've already done it using this:
SELECT *, SUM(`ESTOQUE_FINAL`) OVER (PARTITION BY MATERIAL ORDER BY CALDAY) as ESTOQUE
FROM bq_trusted.IINV_01
ORDER BY MATERIAL, CALDAY
The result is
in this screenshot
What i need now is to get the results on the red circled values. For each MATERIAL, I need the result of the rolling sum by the end of each month.
I can get those results using the following query, but I have to save the last query on a new table to use it.
WITH ESTOQUE_ATUAL AS (
SELECT IQ.*, ROW_NUMBER() OVER (PARTITION BY MATERIAL, MONTH_YEAR ORDER BY CALDAY DESC) AS RN
FROM bq_trusted.INVENTORY AS IQ
)
SELECT * FROM ESTOQUE_ATUAL WHERE RN = 1
ORDER BY MONTH_YEAR
How can I achieve this result using only one query?
Thanks in advance!
Is this what you want?
SELECT i.*
FROM (SELECT i.*,
SUM(ESTOQUE_FINAL) OVER (PARTITION BY MATERIAL ORDER BY CALDAY) as ESTOQUE,
ROW_NUMBER() OVER (PARTITION BY MATERIAL, MONTH_YEAR ORDER BY CALDAY DESC) AS seqnum
FROM bq_trusted.IINV_01 i
) i
WHERE seqnum = 1
ORDER BY MATERIAL, CALDAY
You can calculate both window functions at the same time.

making a query for stock/price trend in mysql

SQL Fiddle
Table scheme:
CREATE TABLE company
(`company_id` int,`name` varchar(30))
;
INSERT INTO company
(`company_id`,`name`)
VALUES
(1,"Company A"),
(2,"Company B")
;
CREATE TABLE price
(`company_id` int,`price` int,`time` timestamp)
;
INSERT INTO price
(`company_id`,`price`,`time`)
VALUES
(1,50,'2015-02-21 02:34:40'),
(2,60,'2015-02-21 02:35:40'),
(1,70,'2015-02-21 05:34:40'),
(2,120,'2015-02-21 05:35:40'),
(1,150,'2015-02-22 02:34:40'),
(2,130,'2015-02-22 02:35:40'),
(1,170,'2015-02-22 05:34:40'),
(2,190,'2015-02-22 05:35:40')
I'm using Cron Jobs to fetch company prices. In concatenating the price history for each company, how can I make sure that only the last one in each day is included? In this case, I want all of the price records around 05:30am concatenated.
This is the result I'm trying to get (I have used Date(time) to only get the dates from the timestamps):
COMPANY_ID PRICE TIME
1 70|170 2015-02-21|2015-02-22
2 120|190 2015-02-21|2015-02-22
I have tried the following query but it doesn't work. The prices don't correspond to the dates and I don't know how to exclude all of the 2:30 am records before applying the Group_concat function.
SELECT company_id,price,trend_date FROM
(
SELECT company_id, GROUP_CONCAT(price SEPARATOR'|') AS price,
GROUP_CONCAT(trend_date SEPARATOR'|') AS trend_date
FROM
(
SELECT company_id,price,
DATE(time) AS trend_date
FROM price
ORDER BY time ASC
)x1
GROUP BY company_id
)t1
Can anyone show me how to get the desired result?
Ok, so this should work as intended:
SELECT p.company_id,
GROUP_CONCAT(price SEPARATOR '|') as price,
GROUP_CONCAT(PriceDate SEPARATOR '|') as trend_date
FROM price as p
INNER JOIN (SELECT company_id,
DATE(`time`) as PriceDate,
MAX(`time`) as MaxTime
FROM price
GROUP BY company_id,
DATE(`time`)) as t
ON p.company_id = t.company_id
AND p.`time` = t.MaxTime
GROUP BY p.company_id
Here is the modified sqlfiddle.
This is a bit unorthodox but I think it solves your problem:
SELECT company_id,
GROUP_CONCAT(price SEPARATOR'|'),
GROUP_CONCAT(trend_date SEPARATOR'|')
FROM (
SELECT *
FROM (
SELECT company_id,
DATE(`time`) `trend_date`,
price
FROM price
ORDER BY `time` DESC
) AS a
GROUP BY company_id, `trend_date`
) AS b
GROUP BY company_id

SQL Sum cumulative and non-cumulative in same query

Hi I was wondering if there is a way to get a cumulative and non-cumulative total in the same query. I have a table with following fields:
Department, SalesPerson, fin_month, activity, cost
What I would like is have two sums, one that would give a monthly total for salesperson, and another giving a year to date total. I am having a problem setting two different where criteria to get it to work.
Many Thanks
Would something like this help?
SELECT
*
FROM
(
SELECT
Department, SalesPerson
, SUM(fin_month) SalesPerson_Sum
FROM
[TABLE_NAME]
GROUP BY Department, SalesPerson
) a
INNER JOIN
(
SELECT
Department
, SUM(fin_month) AS Department_Sum
FROM
[TABLE_NAME]
GROuP BY
Department
) b
ON
a.Department = b.Department
This solution uses CTEs, recursion, and ranking to obtain cumulative totals for every fin_month per SalesPerson in every Department based on the corresponding monthly totals.
;WITH
monthlytotals AS (
SELECT
Department,
SalesPerson,
fin_month,
MonthlyTotal = SUM(cost),
rn = ROW_NUMBER() OVER (PARTITION BY Department, SalesPerson
ORDER BY fin_month)
FROM atable
GROUP BY Department, SalesPerson, fin_month
),
alltotals AS (
SELECT
Department,
SalesPerson,
fin_month,
MonthlyTotal,
CumulativeTotal = MonthlyTotal,
rn
FROM monthlytotals
WHERE rn = 1
UNION ALL
SELECT
m.Department,
m.SalesPerson,
m.fin_month,
m.MonthlyTotal,
CumulativeTotal = a.CumulativeTotals + m.MonthlyTotal,
m.rn
FROM monthlytotals m
INNER JOIN alltotals a
ON m.Department = a.Department
AND m.SalesPerson = a.SalesPerson
AND m.rn = a.rn + 1
)
SELECT
Department,
SalesPerson,
fin_month,
MonthlyTotal,
CumulativeTotal
FROM alltotals