Let's say, I have a table with the following columns:
date | event | user_id | unit_id |cost | ad_id | spend
03-15 | impression | 2353 | 3436 | 0.15 | NULL | NULL
03-15 | impression | 2353 | 3436 | 0.12 | NULL | NULL
03-15 | impression | 1234 | 5678 | 0.10 | NULL | NULL
03-15 | click | 1234 | 5678 | NULL | NULL | NULL
03-15 | create_ad | 1234 | 5678 | NULL | 6789 | 10
I want to calculate how many impressions on average it takes before a user creates an id.
In this particular scenario, it took one impression for user 1234 to create an ad.
I'm not sure that I can somehow use date to discriminate events (but logically all these events should happen at different moments). However, you can see that impressions have NULLs in ad_id and spend, while create_id does have a number in spend.
This one doesn't work:
select i.user_id
, i.unit_id
, count(i.event) impressions_n
, count(c.event) as ads_n
from add4ad i
left
join add4ad c
on i.user_id = c.user_id
and i.unit_id = c.unit_id
where i.event in ('impression')
and c.spend <> NULL
group
by i.user_id
, i.unit_id
I have created a SQLFiddle with this data
I went to SQL Fiddle and ran the test via MS SQL engine.
CREATE TABLE add4ad (date date, event varchar(10), user_id int,
unit_id int, cost float, ad_id float, spend float);
INSERT INTO add4ad (date, Event, user_id,unit_id,cost,ad_id,spend)
VALUES
('2018-03-15','impression','2353','3436','0.15',NULL,NULL),
('2018-03-15','impression','2353','3436','0.12',NULL,NULL),
('2018-03-15','impression','2353','3436','0.10',NULL,NULL),
('2018-03-15','click','1234','5678', NULL, NULL,NULL),
('2018-03-15','create_ad','2353','5678', NULL, 6789,10);
My query
with e10 as (select user_id, event, date, rowid=row_number() over (Partition by user_id order by date)
from add4ad
where event='create_ad'
),
e20 as ( -- get the first create_ad event
select user_id, date
from e10
where rowid=1
)
select a.user_id, count(1) as N
from e20 inner join add4ad a
on e20.user_id=a.user_id
and a.date<=e20.date
and a.event='impression'
group by a.user_id
If I got it right, you need to count distinct ads
CREATE TABLE add4ad (`date` date, `event` varchar(10), `user_id` int,
`unit_id` int, `cost` float, `ad_id` float, `spend` float);
INSERT INTO add4ad (`date`, `Event`, `user_id`,`unit_id`,`cost`,`ad_id`,`spend`)
VALUES
('2018-03-15','impression','2353','3436','0.15',NULL,NULL),
('2018-03-15','impression','2353','3436','0.12',NULL,NULL),
('2018-03-15','impression','2353','3436','0.10',NULL,NULL),
('2018-03-15','impression','1234','5678','0.10',NULL,NULL),
('2018-03-15','click','1234','5678', NULL, NULL,NULL),
('2018-03-15','create_ad','1234','5678', NULL, 6789,10),
('2018-03-16','impression','8765','8871','0.10',NULL,NULL),
('2018-03-16','impression','8765','8871','0.10',NULL,NULL),
('2018-03-16','impression','8765','8871','0.2',NULL,NULL),
('2018-03-16','impression','8765','8871','0.23',NULL,NULL),
('2018-03-16','click','8765','8871', NULL, NULL,NULL),
('2018-03-16','create_ad','8765','8871', NULL, 6789,10);
select i.user_id, i.unit_id, count(i.event) as impressions_n,
count(distinct c.event) as ads_n
from add4ad i
join add4ad c
on i.user_id = c.user_id and i.unit_id = c.unit_id
where i.event in ('impression')
and c.event in ('create_ad') and c.spend is not NULL
group by i.user_id, i.unit_id
Returns
user_id unit_id impressions_n ads_n
1234 5678 1 1
8765 8871 4 1
I've replaced left join with join because where as it is effectively makes your join inner If you still need left join move predicates to ON clause or handle NULLs in where.
fiddle
The issue is for checking NULLS you have to use is NULL or is not NULL. Also your data in fiddle is incorrect. It does not have impression for 1234 in fiddle.
select i.user_id, i.unit_id, count(i.event) as impressions_n,
count(c.event) as ads_n
from add4ad i
left join add4ad c
on i.user_id = c.user_id and i.unit_id = c.unit_id
where i.event in ('impression')
/*and c.event in ('create_ad')*/ and c.spend is not NULL
group by i.user_id, i.unit_id
Seems this is the solution:
select sum(c.impressions_n) / count(1) as average_num_of_impressions from (
select count(i.event) as impressions_n
from add4ad i
join add4ad c
on i.user_id = c.user_id and i.unit_id = c.unit_id
where i.event in ('impression') and c.event in ('create_ad')
group by i.user_id, i.unit_id ) c
I have a table A named patientinfo as shown:
and table b named as tblpayment is as follows:
Now, What I want is to get PatientId and PatientName From Table A JOINING today's paymentDate of Table B and SUM(paymentTotal),SUM(paymentPaid) But LAST row OF paymentRemaining.
In Simple words, I want all the today's patients with SUM of paymentTotal and Sum of paymentPaid but LAST row of paymentRemaining.
Graphically, what I want should be like:
patientId paymentTotal paymentPaid paymentRemaining
252 123500 118500 5000
253 60000 55000 5000
254 17500 17500 0
258 5800 0 5800
NOTE: The record should be of current date.
Any Help?
What I have done so far:
SELECT a.patientId , a.patientName, b.paymentTotal , b.paymentPaid , b.paymentRemaining FROM
patientinfo a
inner join
(
SELECT patienId , SUM(paymentTotal) as paymentTotal ,SUM(paymentPaid) as paymentPaid,
MAX(paymentRemaining) as paymentRemaining
FROM tblpayment WHERE paymentDate LIKE '%$date%' GROUP BY patienId
)b
on a.patientId = b.patienId
Everything is fine, But the error in this query is that it gives me the very first value of column paymentRemaining. Whereas, I want the last value of payment and it is giving me the MAX value. What should I replace this Max with?
EDIT:
A bit mistake in my question. I don't want MAX of paymentRemaining, but LAST row of paymentRemaining of respective patientId.
You just need MIN instead of MAX with LEFT JOIN:
SELECT DISTINCT
t.patientId,
b.paymentTotal ,
b.paymentPaid , b.paymentRemaining
FROM tblpayment AS t
LEFT JOIN patientinfo a ON t.patientId = a.patientId
LEFT join
(
SELECT patientId , SUM(paymentTotal) as paymentTotal,
SUM(paymentPaid) as paymentPaid,
MIN(paymentRemaining) as paymentRemaining
FROM tblpayment
GROUP BY patientId
) b on t.patientId = b.patientId
demo
This will give you exactly what you want:
| patientId | paymentTotal | paymentPaid | paymentRemaining |
|-----------|--------------|-------------|------------------|
| 252 | 123500 | 118500 | 5000 |
| 253 | 60000 | 55000 | 5000 |
| 254 | 17500 | 17500 | 0 |
| 258 | 5800 | 0 | 5800 |
Update:
If you want the last row, then it will be the one with the latest date for each patientid. Then try this:
SELECT DISTINCT
t.patientId,
b.paymentTotal ,
b.paymentPaid ,
t.paymentRemaining
FROM
(
a.patientId, paymentRemaining, paymentDate
FROM tblpayment AS t
LEFT JOIN patientinfo a ON t.patientId = a.patientId
) AS t
INNER join
(
SELECT patientId , SUM(paymentTotal) as paymentTotal,
SUM(paymentPaid) as paymentPaid
FROM tblpayment
GROUP BY patientId
) b on t.patientId = b.patientId
INNER JOIN
(
SELECT patientId, MAX(paymentDate) AS LatestDate
FROM tblpayment
GROUP BY patientId
) AS s ON s.patientId = t.patientId AND t.paymentDate = s.LatestDate
I want to count all the results that have the same value in a mysql query but no matter what i have tried it does not give me the proper value
+-----+---------------+
| RoomType | ID |
+=====+===============+
| dining room | 2 |
+-----+---------------+
| sleeping room | 2 |
+-----+---------------+
| sleeping room | 2 |
+-----+---------------+
and i want to get the count of the sleeping rooms only.
Here is my query:
SELECT rt.RoomType, r.property_id AS ID
FROM Rooms r
INNER JOIN RoomTypes rt ON r.type = rt.id
WHERE r.property_id = '2'
I have also tried
SELECT SUM(IF(rt.RoomType = 'sleeping room', rt.RoomType, 0))
FROM Rooms r
INNER JOIN RoomTypes rt ON r.type = rt.id
WHERE r.property_id = '2'
but it does not give me the results i want. Any ideas?
I have found the answer and a working way like this:
SELECT SUM(rt.RoomType = 'sleeping room')
FROM Rooms r
INNER JOIN RoomTypes rt ON r.type = rt.id
WHERE r.property_id = '2'
and then it gives me the proper result.
Assuming a table like this:
CREATE TABLE `room_types` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`room_type` varchar(64) DEFAULT NULL,
`room_id` int(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=105 DEFAULT CHARSET=utf8'
and some data like this:
1245 dining room 2
1246 bath 3
1247 dining room 2
1248 kitchen 5
104 dining room 2
This should work:
select count(*), room_type, room_id from room_types where room_id = 2 group by room_type;
Result:
3 dining room 2
Hope it helps,
f.u.
I have this freight.or_nos table which contains series of receipt numbers. I want to list all the or's being issued excluding the status='Cancelled' making the series broken in groups.
For example I have this receipt stab 125001-125050, and 125020 is cancelled so the listing result would be:
+-------------------------------------------------------+
| OR Start | OR End | Quantity | Amount |
+-------------------------------------------------------+
| 125001 | 125019 | 19 | |
+-------------------------------------------------------+
| 125021 | 125050 | 30 | |
+-------------------------------------------------------+
This seems to be a tough query.
Thanks for reading but I already made it, just now! :)
Here's my query(disregard the other characters it's form our CGI):
{.while SELECT `start`,`end`,or_prefix,or_suffix,SUM(a.amount) AS g_total,COUNT(*) AS qcount FROM (SELECT l.id AS `start`,( SELECT MIN(a.id) AS id FROM ( SELECT a.or_no AS id FROM freight.`or_nos` a WHERE a.status!='Cancelled' AND a.log_user = 0#user_teller AND DATE(a.or_date)='#user_date`DATE' AND IF(a.status='Default' AND a.amount=0,0,1) ) AS a LEFT OUTER JOIN ( SELECT a.or_no AS id FROM freight.`or_nos` a WHERE a.status!='Cancelled' AND a.log_user = 0#user_teller AND DATE(a.or_date)='#user_date`DATE' AND IF(a.status='Default' AND a.amount=0,0,1) ) AS b ON a.id = b.id - 1 WHERE b.id IS NULL AND a.id >= l.id ) AS `end` FROM ( SELECT a.or_no AS id FROM freight.`or_nos` a WHERE a.status!='Cancelled' AND a.log_user = 0#user_teller AND DATE(a.or_date)='#user_date`DATE' AND IF(a.status='Default' AND a.amount=0,0,1) ) AS l LEFT OUTER JOIN ( SELECT a.or_no AS id FROM freight.`or_nos` a WHERE a.log_user = 0#user_teller AND DATE(a.or_date)='#user_date`DATE' AND IF(a.status='Default' AND a.amount=0,0,1) ) AS r ON r.id = l.id - 1 WHERE r.id IS NULL) AS k LEFT JOIN freight.`or_nos` a ON a.`or_no` BETWEEN k.start AND k.end AND DATE(a.`or_date`)='#user_date`DATE' AND a.log_user =0#user_teller AND IF(a.status='Default' AND a.amount=0,0,1) AND a.status!='Cancelled' GROUP BY `start`}
{.start}{.x.24.12:end}{.x`p0.40.-5:qcount}{.x`p2.57.-15:g_total}{.asc 255}
{.wend}{.asc 255}
I have three tables actually on virturt mart table one is orders, another is item & one is order_user_info
to get the user first name i need to join order_user_info table
but when i join it shows the result info double, below i have mentioned the query & result please guide how can avoid double result
*FOR JOIN FIRST NAME I AM USING BELOW MENTIONED QUERY *
LEFT JOIN `urbanite_virtuemart_order_userinfos` as Uinfo ON Uinfo.virtuemart_order_id=i.virtuemart_order_id
*COMPLETE QUERY *
SELECT SQL_CALC_FOUND_ROWS o.created_on AS intervals, CAST( i.`created_on` AS DATE ) AS created_on, Uinfo.`first_name`, o.`order_number`, SUM(DISTINCT i.product_item_price * product_quantity) as order_subtotal_netto, SUM(DISTINCT i.product_subtotal_with_tax) as order_subtotal_brutto, COUNT(DISTINCT i.virtuemart_order_id) as count_order_id, SUM(i.product_quantity) as product_quantity FROM `urbanite_virtuemart_order_items` as i
LEFT JOIN `urbanite_virtuemart_orders` as o ON o.virtuemart_order_id=i.virtuemart_order_id
LEFT JOIN `urbanite_virtuemart_order_userinfos` as Uinfo ON Uinfo.virtuemart_order_id=i.virtuemart_order_id AND Uinfo.created_on = i.created_on AND Uinfo.virtuemart_user_id = o.virtuemart_user_id
WHERE (`i`.`order_status` = "S") AND i.virtuemart_vendor_id = "63" AND DATE( o.created_on ) BETWEEN "2013-06-01 05:00:00" AND "2013-06-30 05:00:00"
GROUP BY intervals
ORDER BY created_on DESC LIMIT 0, 400
result i am getting with out join like below
intervals | Created_on | order_no | order_subtotalnetto | order_subtotalbruto | count_order_id | product_quantity
2013-06-12 09:47:16 |2013-06-12 | 43940624 | 200.00000 | 200.00000 | 1 | 2
result i am getting with join for firstname like below
intervals | Created_on | order_no | f_name | order_subtotalnetto | order_subtotalbruto | count_order_id | product_quantity
2013-06-12 09:47:16 |2013-06-12 | Fatin Bokhari | 43940624 | 200.00000 | 200.00000 | 1 | 4
see in with out join for first name it show product_quantity = 2 but when i join it shows the value double, i tried distinct but cant go this way as it show the product quantity = 1 every time
Kindly need rescue!
oh actually the rows comes twice in a urbanite_virtuemart_order_userinfos table so i used where clause & it works
WHERE (`i`.`order_status` = "S") AND i.virtuemart_vendor_id = "63" AND DATE( o.created_on ) BETWEEN "2013-06-01 05:00:00" AND "2013-06-30 05:00:00" AND Uinfo.`address_type` = 'BT'