How to use multiple aggregate function with group by - mysql

I have three tables in advertiser,advertiser_clicks and advertiser_cost in which i have used join with multiple aggregate function.But i was unable to get the actual record from the tables.Please find below my table structure.
Table1:advertiser
................
id name
................
1 Your Survey
2 Vindale
Table2:advertiser_clicks
In this table adv_id is foreign key of advertiser table id
.............................................................
id adv_id survey_id survey_name clicks dt_datetime
.............................................................
1 1 101 survey1 1 2017-11-30
2 2 102 survey2 1 2017-11-29
3 1 103 survey3 1 2017-11-28
Table3:advertiser_cost
In this table a_click_id is the foreign key of advertiser_clicks table adv_id
.......................................................
ac_id a_click_id cpi conversion cost profit
......................................................
1 1 10 1 8 2
2 2 10 1 5 5
3 3 5 1 5 5
I want below output:-when i select start date:2017-11-29 and enddate :2017-11-30 in where condition then i want below output.Here total click,cpi,cost & profit is the sum of all the data which comes in between that daterange.
.............................................................
adv_id advertiser totalclick cpi cost profit
.............................................................
1 Your survey 2 20 13 8
2 vindale 0 0 0 0
I have write the below query which returns the exact data which comes
in between that date range but i it will not return the record of vindale
advertiser as a zero value.Please find my below query.
SELECT sum(advertiser_clicks.`clicks`) as totalclick,sum(advertiser_cost.cpi) as revenue,sum(advertiser_cost.`conversion`) as conversion,sum(advertiser_cost.`cost`) as cost,SUM(advertiser_cost.profit) as profit,advertiser.name as advertiser,advertiser.id as adv_id FROM `advertiser_clicks` LEFT JOIN advertiser_cost on advertiser_cost.a_click_id=advertiser_clicks.`id` inner join advertiser on advertiser.id=advertiser_clicks.`adv_id` where advertiser_clicks.`dt_datetime`>='2017-11-29' and advertiser_clicks.`dt_datetime`<='2017-11-30' group by advertiser.name,advertiser.id
My query return this output:-
.............................................................
adv_id advertiser totalclick cpi cost profit
.............................................................
1 Your survey 2 20 13 8

Hi i have resolved my issue:-
SELECT sum(advertiser_clicks.`clicks`) as totalclick,sum(advertiser_cost.cpi) as revenue,sum(advertiser_cost.`conversion`) as conversion,sum(advertiser_cost.`cost`) as cost,SUM(advertiser_cost.profit) as profit,advertiser.name as advertiser,advertiser.id as adv_id FROM `advertiser` left join advertiser_clicks on advertiser.id=advertiser_clicks.`adv_id` and (advertiser_clicks.`dt_datetime` between '$startdate' and '$enddate' ) LEFT JOIN advertiser_cost on advertiser_cost.a_click_id=advertiser_clicks.`id` group by advertiser.name,advertiser.id

Related

how to comparison LAG function in mysql

I got complicated problem in mysql.
I have some table on mydatabase.
sample docs(this is only simple sample, actual data are so many table that I have to join)
table "merchant"
id name
1 arief
2 john
3 chena
table "transaction"
id product_id price merchant_id date
1 1 20000 2 2020-02-01
2 5 25000 1 2020-02-01
3 2 10000 3 2020-02-02
4 2 10000 2 2020-02-02
5 3 5000 2 2020-02-02
5 2 10000 2 2020-02-03
6 3 5000 3 2020-02-04
I want to know the information of merchants transaction daily "before" and "after" to comparison
like this below
name_merchant sumtrx_20-02-01 sumtrx_20-02-02 sumtrx_20-02-03 sumtrx_20-02-04
arief 1 0 0 0
john 1 2 1 0
chena 0 1 0 1
I tried with this query
select m.name, count(trx.id, trx.date = '2020-02-01') as sumtrx_20-02-01, count(trx.id, trx.date = '2020-02-02') as sumtrx_20-02-02, count(trx.id, trx.date = '2020-02-03') as sumtrx_20-02-03, count(trx.id, trx.date = '2020-02-04') as sumtrx_20-02-04 from merchant as m join transaction as trx on m.id = trx.merchant_id
group by m.name
but that query didn't work
You can use sum() instead of count().
SELECT m.name,
sum(trx.date = '2020-02-01') `sumtrx_20-02-01`,
...
sum(trx.date = '2020-02-04') `sumtrx_20-02-04`
FROM merchant m
INNER JOIN transaction trx
ON m.id = trx.merchant_id
GROUP BY m.name;
And you also need to enclose identifiers, here the column aliases, in backticks if you use special characters like - in them. Or avoid using special characters in them all together.

SQL - Max value from a group by when creating a new field

I have a database with a table called BOOKINGS containing the following values
main-id place-id start-date end-date
1 1 2018-8-1 2018-8-8
2 2 2018-6-6 2018-6-9
3 3 2018-5-5 2018-5-8
4 4 2018-4-4 2018-4-5
5 5 2018-3-3 2018-3-10
5 1 2018-1-1 2018-1-6
4 2 2018-2-1 2018-2-10
3 3 2018-3-1 2018-3-28
2 4 2018-4-1 2018-4-6
1 5 2018-5-1 2018-5-15
1 3 2018-6-1 2018-8-8
1 4 2018-7-1 2018-7-6
1 1 2018-8-1 2018-8-18
1 2 2018-9-1 2018-9-3
1 5 2018-10-1 2018-10-6
2 5 2018-11-1 2018-11-5
2 3 2018-12-1 2018-12-25
2 2 2018-2-2 2018-2-19
2 4 2018-4-4 2018-4-9
2 1 2018-5-5 2018-5-23
What I need to do is for each main-id I need to find the largest total number of days for every place-id. Basically, I need to determine where each main-id has spend the most time.
This information must then be put into a view, so unfortunately I can't use temporary tables.
The query that gets me the closest is
CREATE VIEW `MOSTTIME` (`main-id`,`place-id`,`total`) AS
SELECT `BOOKINGS`.`main-id`, `BOOKINGS`.`place-id`, SUM(DATEDIFF(`end-date`, `begin-date`)) AS `total`
FROM `BOOKINGS`
GROUP BY `BOOKINGS`.`main-id`,`RESERVATION`.`place-id`
Which yields:
main-id place-id total
1 1 24
1 2 18
1 5 5
2 1 2
2 2 20
2 4 9
3 1 68
3 2 24
3 3 30
4 1 5
4 2 10
4 4 1
5 1 19
5 2 4
5 5 7
What I need is then the max total for each distinct main-id:
main-id place-id total
1 1 24
2 2 20
3 1 68
4 2 10
5 1 19
I've dug through a large amount of similar posts that recommend things like self joins; however, due to the fact that I have to create the new field total using an aggregate function (SUM) and another function (DATEDIFF) rather than just querying an existing field, my attempts at implementing those solutions have been unsuccessful.
I am hoping that my query that got me close will only require a small modification to get the correct solution.
Having hyphen character - in column name (which is also minus operator) is a really bad idea. Do consider replacing it with underscore character _.
One possible way is to use Derived Tables. One Derived Table is used to determine the total on a group of main id and place id. Another Derived Table is used to get maximum value out of them based on main id. We can then join back to get only the row corresponding to the maximum value.
CREATE VIEW `MOSTTIME` (`main-id`,`place-id`,`total`) AS
SELECT b1.main_id, b1.place_id, b1.total
FROM
(
SELECT `main-id` AS main_id,
`place-id` AS place_id,
SUM(DATEDIFF(`end-date`, `begin-date`)) AS total
FROM BOOKINGS
GROUP BY main_id, place_id
) AS b1
JOIN
(
SELECT dt.main_id, MAX(dt.total) AS max_total
FROM
(
SELECT `main-id` AS main_id,
`place-id` AS place_id,
SUM(DATEDIFF(`end-date`, `begin-date`)) AS total
FROM BOOKINGS
GROUP BY main_id, place_id
) AS dt
GROUP BY dt.main_id
) AS b2
ON b1.main_id = b2.main_id AND
b1.total = b2.max_total
MySQL 8+ solution would be utilizing the Row_Number() functionality:
CREATE VIEW `MOSTTIME` (`main-id`,`place-id`,`total`) AS
SELECT b.main_id, b.place_id, b.total
FROM
(
SELECT dt.main_id,
dt.place_id,
dt.total
ROW_NUMBER() OVER (PARTITION BY dt.main_id
ORDER BY dt.total DESC) AS row_num
FROM
(
SELECT `main-id` AS main_id,
`place-id` AS place_id,
SUM(DATEDIFF(`end-date`, `begin-date`)) AS total
FROM BOOKINGS
GROUP BY main_id, place_id
) AS dt
GROUP BY dt.main_id
) AS b
WHERE b.row_num = 1

MySQL join next lower value from other table

I've the two tables orders
id article amount
1 1 1
2 2 50
and prices
id article min_amount price
1 1 1 42.99
2 2 1 5.06
3 2 5 4.55
4 2 10 4.3
5 2 25 4.05
6 2 100 2.66
The prices tables contains IDs of articles and a minimum amount you would have to buy to get a bulk discount (which would change the price for the order). I would like to join prices into orders, so that the result looks like:
id article amount price
1 1 1 42.99
2 2 50 4.05
The order id 2 is above the minimum (25) to get the article for 4.05€, but still below 100 at which you would get a bigger discount, so the query would to have pick the next-lower value.
I've tried this query so far
SELECT
orders.id AS id,
orders.article,
orders.amount,
prices.price,
(orders.amount - prices.min_amount) AS discount_diff
FROM orders
LEFT JOIN prices ON (prices.article = orders.article) AND (prices.min_amount <= orders.amount)
which gives this result
id article amount price discount_diff
1 1 1 42.99 0
2 2 50 5.06 49
2 2 50 4.55 45
2 2 50 4.3 40
2 2 50 4.05 25
You can find this example on "js"fiddle: http://sqlfiddle.com/#!9/1b2bf/8
The query you need is this:
SELECT orders.id AS id,
orders.article,
orders.amount,
prices.price
FROM orders
INNER JOIN prices ON ( prices.article = orders.article
and prices.min_amount <= orders.amount)
INNER JOIN ( SELECT orders.article,
orders.amount,
min(prices.price) minprince
FROM orders
INNER JOIN prices ON (prices.article = orders.article
AND prices.min_amount <= orders.amount)
GROUP BY orders.article,
orders.amount) b
ON ( prices.article = b.article
AND orders.amount = b.amount
AND prices.price = b.minprince)
See it here: http://sqlfiddle.com/#!9/1b2bf/27

How to get last value and sum a group of values in sql?

I'm trying to do get the last value of net_insurance of each policy and sum by type_money
|policies|
|id| |policy_num| |type_money|
1 1234 1
2 5678 1
3 3444 2
4 4577 2
|insurances|
|id| |policy_id| |net_insurance|
1 1 100
2 1 200
3 1 400
4 2 500
5 2 600
6 3 100
7 4 200
Here I'm trying to get the last value
semi result bedore to do the sum
|policy_num| |type_money| |last_net_insurance|
1234 1 400
5678 1 600
3444 2 100
4577 2 200
After getting the last value I want to sum by type_money that's what I really need
|type money| |sum|
1 1000
2 300
I tried this but I don't know how to get the last net_insurance of each policy and also do a sum
select * from policies
inner join insurances ON (insurances.policy_id =policies.id)
group by policies.id
Here is the page where I'm doing this
http://sqlfiddle.com/#!2/acd8e/3
Here it is:
SELECT p.type_money, sum(i1.net_insurance) total FROM (
SELECT max(id) id FROM insurances
GROUP BY policy_id
) i2
JOIN insurances i1 USING (id)
JOIN policies p ON p.id = i1.policy_id
GROUP BY p.type_money
Fiddle here.
BTW, absolute +1 for providing the fiddle and adding your sample query :)

MySQL Date range incorrect result obtained - Query ignores the specified range

I have a query that involves searching database over a range of 30 days. Queries, both with correct output and wrong output are below:
CORRECT RESULTS:
SELECT
affiliates.member_id,
IFNULL( COUNT(orders.deal_id) , 0 ) AS deals_count,
IFNULL( SUM(orders.quantity) , 0 ) AS deals_quanity
FROM affiliates
LEFT JOIN deals ON affiliates.member_id = deals.member_id
LEFT JOIN orders ON deals.deal_id = orders.deal_id
LEFT JOIN customers_orders_link ON orders.order_id = customers_orders_link.order_id
AND DATE(customers_orders_link.datetime) BETWEEN '2011-06-01' AND '2011-07-01'
AND customers_orders_link.order_status = 'Delivered'
GROUP BY affiliates.member_id;
EXPECTED & RECEIVED: (Correct)
MemberID COUNT SUM
1 11 16
2 0 0
WRONG RESULTS:
//Notice the change in the date range
SELECT
affiliates.member_id,
IFNULL( COUNT(orders.deal_id) , 0 ) AS deals_count,
IFNULL( SUM(orders.quantity) , 0 ) AS deals_quanity
FROM affiliates
LEFT JOIN deals ON affiliates.member_id = deals.member_id
LEFT JOIN orders ON deals.deal_id = orders.deal_id
LEFT JOIN customers_orders_link ON orders.order_id = customers_orders_link.order_id
AND DATE(customers_orders_link.datetime) BETWEEN '2011-10-01' AND '2011-10-31'
AND customers_orders_link.order_status = 'Delivered'
GROUP BY affiliates.member_id
EXPECTED:
MemberID COUNT SUM
1 0 0
2 0 0
BUT I RECEIVE: (INCORRECT OUTPUT)
MemberID COUNT SUM
1 11 16
2 0 0
The first query is producing correct results whereas the second query is producing incorrect results. Even if I use a date in the past as the range, I still receive the same Incorrect Output. Its as if the query is completely ignoring the date range specification. So this case of ignoring the date range specification seems to be the problem.
How can I make the query "see" and "obey" the date range specification and actually receive the Expected Output for the 2nd query listed above?
EDIT 1:
//Table: Orders
order_id deal_id quantity price
1 1 2 40.00
1 2 1 15.00
2 1 1 20.00
3 9 1 5.00
4 1 2 40.00
4 9 2 10.00
5 1 1 20.00
5 9 1 5.00
6 1 2 40.00
6 9 2 10.00
7 1 1 20.00
8 11 1 1.00
//Table: customers_orders_link
order_id customer_id order_status datetime
1 4 Cancelled 2011-06-05 20:26:45
2 4 Delivered 2011-06-05 20:38:28
3 4 Pending Payment 2011-06-05 20:56:50
4 4 Pending Payment 2011-06-09 17:03:08
5 4 Pending Payment 2011-06-09 17:12:23
6 4 Pending Payment 2011-06-09 17:19:57
7 4 Pending Payment 2011-06-09 17:40:59
8 4 Pending Payment 2011-06-10 03:55:17
I solved it myself using a totally different method.
I don't know what your data looks like, but I suspect your LEFT JOIN customers_orders_link is to blame. If you only want to tally COUNT() and SUM() when the conditions of that table are met, it should be a standard JOIN in place of a LEFT JOIN.