I am having trouble querying the correct date range. My query does not seem to consider the Where clause for post_date > (date provided).
SELECT `code`,
`description`,
SUM( IF( month = 3 && year = 2018, monthly_quantity_total, 0 ) ) AS monthlyqt,
SUM( IF( month = 3 && year = 2018, monthly_price_total, 0 ) ) AS monthlypt,
SUM( monthly_quantity_total ) AS yearlyqt,
SUM( monthly_price_total ) AS yearlypt
FROM (
SELECT `invoices_items`.`code`,
`invoices_items`.`description`,
SUM( invoices_items.discounted_price * invoices_items.quantity_supplied ) AS monthly_price_total,
SUM( invoices_items.quantity_supplied ) AS monthly_quantity_total,
YEAR( invoices_items.datetime_created ) AS year,
MONTH( invoices_items.datetime_created ) AS month
FROM `invoices_items`
JOIN `invoices` ON `invoices`.`id` = `invoices_items`.`invoice_id`
WHERE `invoices`.`is_finalised` = 1
AND `invoices`.`post_date` > 2018-02-28
AND `invoices_items`.`type` = 1
GROUP BY `year`, `month`, `invoices_items`.`code`
UNION ALL
SELECT `credit_notes_items`.`code`,
`credit_notes_items`.`description`,
SUM( credit_notes_items.discounted_price * credit_notes_items.quantity_supplied * -1 ) AS monthly_price_total,
SUM( credit_notes_items.quantity_supplied ) AS monthly_quantity_total,
YEAR( credit_notes_items.datetime_created ) AS year,
MONTH( credit_notes_items.datetime_created ) AS month
FROM `credit_notes_items`
JOIN `credit_notes` ON `credit_notes`.`id` = `credit_notes_items`.`credit_note_id`
WHERE `credit_notes`.`is_finalised` = 1
AND `credit_notes`.`post_date` > 2018-02-28
AND `credit_notes_items`.`type` = 1
GROUP BY `year`, `month`, `credit_notes_items`.`code`
) AS sub
GROUP BY code;
There are basically 4 tables being queried here. invoices, invoices_items, credit_notes and credit_notes_items.
table 1 - invoices
id post_date is_finalised
1 2018-01-01 1
2 2018-02-01 1
3 2018-03-01 1
table 2 - invoices_items
id invoice_id code description discounted_price quantity_total type
1 1 TEST-01 Test product 9.99 1 1
2 1 TEST-01 Test product 9.99 2 1
3 2 TEST-01 Test product 9.99 5 1
4 3 TEST-01 Test product 9.99 5 1
I have give some example rows above. From the table 1 and 2 above the desired result should be;
Desired Output
code description monthyqt monthlypt yearlyqt yearlypt
TEST-01 Test product 5 49.95 5 49.95
However the output I am receiving is as below;
Received Output
code description monthyqt monthlypt yearlyqt yearlypt
TEST-01 Test product 5 49.95 13 129.87
The query works as intended except for the date range I am trying to achieve by using the Where clause. You can see I am trying to filter out any row which are not matching invoices.post_date > 2018-02-28 (and also credit_notes.post_date > 2018-02-28).
I am not sure what I have done wrong here but any help will be much appreciated.
Thanks in advance.
I worked it out. Basically the variable which was parsing the date value needed to be encapsulated in single quotes.
e.g.
invoices.post_date > '2018-02-28'
It's always something this simple which throws you off.
Related
I have two tables namely "appointment" and "skills_data".
Structure of appointment table is:
id_ap || ap_meet_date || id_skill || ap_status.
And the value of ap_status are complete, confirm, cancel and missed.
And the skills_data table contains two columns namely:
id_skill || skill
I want to get the count of total number of appointments for each of these conditions
ap_status = ('complete' and 'confirm'),
ap_status = 'cancel' and
ap_status = 'missed'
GROUP BY id_skill and year and
order by year DESC
I tried this query which only gives me count of one condition but I want to get other two based on group by and order by clauses as mentioned.
If there is no record(for example: zero appointments missed in 2018 for a skill) matching for certain conditions, then it should display the output value 0 for zero count.
Could someone please suggest me with a query whether I should implement multiple select query or CASE clause to achieve my expected results. I have lot of records in appointment table and want a efficient way to query my records. Thank you!
SELECT a.id_skill, YEAR(a.ap_meet_date) As year, s.skill,COUNT(*) as count_comp_conf
FROM appointment a,skills_data s WHERE a.id_skill=s.id_skill and a.ap_status IN ('complete', 'confirm')
GROUP BY `id_skill`, `year`
ORDER BY `YEAR` DESC
Output from my query:
id_skill | year | skill | count_comp_conf
-----------------------------------------
1 2018 A 20
2 2018 B 15
1 2019 A 10
2 2019 B 12
3 2019 C 10
My expected output should be like this:
id_skill | year | skill | count_comp_conf | count_cancel | count_missed
------------------------------------------------------------------------
1 2018 A 20 5 1
2 2018 B 15 8 0
1 2019 A 10 4 1
2 2019 B 12 0 5
3 2019 C 10 2 2
You can use conditional aggregation using case when expression
SELECT a.id_skill, YEAR(a.ap_meet_date) As year, s.skill,
COUNT(case when a.ap_status IN ('complete', 'confirm') then 1 end) as count_comp_conf,
COUNT(case when a.ap_status = 'cancel' then 1 end) as count_cancel,
COUNT(case when a.ap_status = 'missed' then 1 end) as count_missed
FROM appointment a inner join skills_data s on a.id_skill=s.id_skill
GROUP BY `id_skill`, `year`
ORDER BY `YEAR` DESC
SELECT a.id_skill,
YEAR(a.ap_meet_date) As year,
s.skill,
SUM(IF(a.ap_status IN ('complete', 'confirm'),1,0)) AS count_comp_conf,
SUM(IF(a.ap_status='cancel',1,0)) AS count_cancel,
SUM(IF(a.ap_status='missed',1,0)) AS count_missed
FROM appointment a,skills_data s WHERE a.id_skill=s.id_skill
GROUP BY `id_skill`, `year`
ORDER BY `YEAR` DESC;
Please try to use if condition along with sum.
With below query you will get output.
select id_skill ,
year ,
skill ,
count_comp_conf ,
count_cancel ,
count_missed ( select id_skill, year, skill, if ap_status ='Completed' then count_comp_conf+1, elseif ap_status ='cancelled' then count_cancel +1 else count_missed+1
from appointment a join skills_data s on (a.id_skill = s.id_skill) group by id_skill, year) group by id_skill,year
order by year desc;
Having trouble wrapping my head around having an efficient "duplicate entries" select in a single query.
In the below example, duplicate StockNo can exist spanning multiple Date. I want to search StockNo for duplicate entries, and if at least 1 StockNo record is found within the Date current YEAR-MONTH, then I also need to select its partner that could exist in any other YEAR-MONTH. Is this possible?
Example Query:
SELECT * FROM `sales`
WHERE `StockNo` IN
(SELECT `StockNo` FROM `sales` GROUP BY `StockNo` HAVING COUNT(*) > 1)
AND `Date` LIKE '2016-11-%'
ORDER BY `StockNo`, `TransactionID`;
Example Data:
ID | StockNo | Date
1 | 1 | 2016-11-01
2 | 1 | 2016-11-10
3 | 2 | 2016-11-05
4 | 2 | 2016-10-29
5 | 3 | 2016-10-25
6 | 3 | 2016-10-15
With my example query and data, I have 3 pairs of duplicate entries. It's pretty obvious that I will only return 3 records (ID's 1, 2 & 3) due to AND Date LIKE '2016-11-%', however I need to return ID's 1, 2, 3, 4. I want to ignore ID's 5 & 6 because neither of them fall within the current month.
Hope that makes sense. Thanks for any help you can provide.
SELECT StockNo
FROM sales
GROUP BY StockNo
HAVING SUM(CASE WHEN DATE_FORMAT(Date, '%Y-%m') = '2016-11' THEN 1 ELSE 0 END) > 0
If you also want to retrieve the full records for those matching stock numbers in the above query, you can just add a join:
SELECT s1.*
FROM sales s1
INNER JOIN
(
SELECT StockNo
FROM sales
GROUP BY StockNo
HAVING SUM(CASE WHEN DATE_FORMAT(Date, '%Y-%m') = '2016-11' THEN 1 ELSE 0 END) > 0
) s2
ON s1.StockNo = s2.StockNo
Demo here:
SQLFiddle
Thank you very much Tim for pointing me in the right direction. Your answer was close but it still only returned records from the current month and in the end I used the following query:
SELECT s1.* FROM `sales` s1
INNER JOIN
(
SELECT * FROM `sales` GROUP BY `StockNo` HAVING COUNT(`StockNo`) > 1
AND SUM(CASE WHEN DATE_FORMAT(`Date`, '%Y-%m')='2016-11' THEN 1 ELSE 0 END) > 0
) s2
ON s1.StockNo=s2.StockNo
This one had been eluding me for some time.
I have a table with columns: cid, date
Sample table data: Note: cid contains string values eg: 'otsytb8o7sbs50w9doghwzvfy0vb8f9h' many are duplicated.
cid. date
--------------------------------------------------------
1 2015-10-10 04:57:57
2 2015-10-10 05:03:58
3 2015-10-10 05:24:49
4 2015-10-10 05:28:24
5 2015-10-10 05:28:26
6 2015-10-10 05:28:40
7 2015-10-10 05:30:39
8 2015-10-10 05:33:04
9 2015-10-10 05:35:42
9 2015-10-10 05:36:03
I want to get the following:
Count of Distinct cid as uniqVisits
Count of cid HAVING (count <= 1) as bounced
Grouped by month
I want to get bounce rate per month from Cookie ID's (cid).
So I am looking for: ( COUNT of unique Cookie ID's with a count of <=1 ) for bounced, and ( COUNT DISTINCT cid's ) for total unique visitors, Grouped By month
Desired result:
uniqVisits | bounced | month
-----------|---------|-------
2345 | 325 | 2015-10
-----------|---------|-------
7345 | 734 | 2015-11
-----------|---------|-------
3982 | 823 | 2015-12
-----------|---------|-------
4291 | 639 | 2016-01
I have tried a lot of methods the below is the closest I can get but it gives me error: "Operand should contain 1 column(s)"
SELECT count(*) AS bounced,
( SELECT count( DISTINCT(cid) ) AS uniqVisits,
SUBSTR(DATE(date),1,7) AS month
FROM table ) AS uniqVisits
FROM (
SELECT COUNT(cid) AS bounced,
SUBSTR(DATE(date),1,7) AS month
FROM table
GROUP BY cid
HAVING (count <= 1)
) AS x
GROUP BY month
How can I write this query to give me the desired result I want in the "Desired result:" chart / table illustrated above?
BTW: I also tried the below query but it times out, and then throws a server error: It also does not group the second query into month, obviously because of the "cid having count <=1"
SELECT c1.uniqVisits,
c1.month,
c2.bounced
FROM ( SELECT COUNT(DISTINCT t1.cid) AS `uniqVisits`,
SUBSTR(DATE(t1.date),1,7) AS `month`
FROM table t1
GROUP BY month
) c1
JOIN ( SELECT COUNT(*) AS `bounced`,
SUBSTR(DATE(t2.date),1,7) AS `month`
FROM table t2
GROUP BY month, cid HAVING (count <= 1)
) c2
ON c2.month = c1.month
ORDER BY c1.month
So I have resolved this:
SELECT uniqVisitors, COUNT(*) AS bounced, T1.month
FROM (
SELECT cid,
SUBSTR(DATE(date),1,7) AS month
FROM table
GROUP BY cid
HAVING COUNT(*) <= 1
) T1
LEFT JOIN
( SELECT count( DISTINCT(cid) ) AS uniqVisitors,
SUBSTR(DATE(date),1,7) AS month
FROM table
GROUP By month ) T2
ON T1.month = T2.month
GROUP BY month
Gives me:
uniqVisitors | bounced | month
---------------------------------
7237 6822 2015-10
12597 12136 2015-11
12980 12573 2015-12
12091 11695 2016-01
5396 5134 2016-02
I have a table called code_status:
Code Message
1 "Start"
2 "In process"
3 "Finish"
And another table called history
ID Code Name time_date
1 2 Jon 1/2/15
31 1 Abby 2/1/15
12 3 Sara 3/3/15
31 2 Abby 2/3/15
31 3 Abby 2/5/15
8 2 Max 1/22/15
I want to create an history_view with the following schema:
history_view (id, name, start_date, process_date, finish_date)
If the date is not given, it would just be NULL
So it would look like
ID Name start_date process_date finish_date
31 Abby 2/1/15 2/3/15 2/5/15
1 Jon NULL 1/2/15 NULL
... etc
So i started off by doing :
CREATE VIEW history_view
AS SELECT h.id, h.name,
(CASE WHEN h.code = 1 THEN time_date) AS start_date,
(CASE when h.code = 2 THEN time_date) AS process_date,
(CASE when h.code = 3 THEN time_date) AS finish_date
FROM history h;
I would get a result like the following below though:
ID Name start_date process_date finish_date
31 Abby 2/1/15 NULL NULL
31 Abby NULL 2/3/15 NULL
31 Abby NULL NULL 2/5/15
... ETC
Is there any way to consolidate the rows together ?
When you say consolidate you're referring to aggregation, you can use an aggregate function, such as min:
CREATE VIEW history_view
AS SELECT h.id, h.name,
min(CASE WHEN h.code = 1 THEN time_date) AS start_date,
min(CASE when h.code = 2 THEN time_date) AS process_date,
min(CASE when h.code = 3 THEN time_date) AS finish_date
FROM history h
group by h.id, h.name;
I have been stumped on this for quite awhile. Request#, SlotId, Segment, and Version all make up the primary key. What i want from my stored proc is to be able to retrieve all rows by passing in the Request # and Segment, but for each slot i want the most recent effective date on or before todays date and from that i need the highest version #. I appriciate your time.
Values in database
Request# SlotId Segment Version Effective Date ContentId
A123 1 A 1 2012-01-01 1
A123 2 A 1 2012-01-01 2
A123 2 A 2 2012-02-01 34
A123 2 A 3 2012-02-01 24
A123 2 A 4 2015-01-01 6 //beyond todays date. dont want
Values I want to return from my stored proc when i pass in A123 for Request # and A for Segment.
A123 1 A 1 2012-01-01 1
A123 2 A 3 2012-02-01 24
The query could be written like this:
; WITH cte AS
( SELECT Request, SlotId, Segment, Version, [Effective Date], ContentId,
ROW_NUMBER() OVER ( PARTITION BY Request, Segment, SlotId
ORDER BY Version DESC ) AS RowN
FROM
tableX
WHERE
Request = #Req AND Segment = #Seg --- the 2 parameters
AND [Effective Date] < DATEADD(day, 1, GETDATE())
)
SELECT Request, SlotId, Segment, Version, [Effective Date], ContentId
FROM cte
WHERE Rn = 1 ;
Consider this:
;
WITH A as
(
SELECT DISTINCT
Request
, Segment
, SlotId
FROM Table1
)
SELECT A.Request
, A.SlotId
, A.Segment
, B.EffectiveDate
, B.Version
, B.ContentID
FROM A
JOIN (
SELECT Top 1
Request
, SlotId
, Segment
, EffectiveDate
, Version
, ContentId
FROM Table1 t1
WHERE t1.Request = A.Request
AND t1.SlotId = A.SlotId
AND T1.Segment = A.Segment
AND T1.EffectiveDate <= GetDate()
ORDER BY
T1.EffectiveDate DESC
, T1.Version DESC
) as B
ON A.Request = B.Request
AND A.SlotId = B.SlotId
AND A.Segment = B.Segment