Unrecognized statement type. (near with) - mysql

I have query like below for get sum of purchase and sold traffic.
SELECT DATE_FORMAT(order_time,'%d')AS date,
SUM(CASE WHEN seller_id = 1 THEN visitor_quantity ELSE 0 END) AS totalSold,
SUM(CASE WHEN buyer_id = 1 THEN visitor_quantity ELSE 0 END) AS totalBought
FROM `tbl_orders`
WHERE buyer_id = 1 OR seller_id = 1
GROUP BY DATE(order_time)
Its working fine and giving me result like below
Since I am looking for get all dates between provided date range with 0 if there no any record for that date.
So I am trying following query
with recursive all_dates(dt) as (
-- anchor
select '2021-12-01' dt
union all
-- recursion with stop condition
select dt + interval 1 day from all_dates where dt + interval 1 day <= '2021-12-31'
)SELECT DATE_FORMAT(order_time,'%d')AS date,SUM(CASE
WHEN seller_id = 1
THEN visitor_quantity
ELSE 0
END) AS totalSold, SUM(CASE
WHEN buyer_id = 1
THEN visitor_quantity
ELSE 0
END) AS totalBought FROM `tbl_orders` WHERE buyer_id = 1 OR seller_id = 1 GROUP BY DATE(order_time)
I have found query tutorial here.
But its giving me error called Unrecognized statement type. (near with) in phpmyadmin and giving same result as above image.
my phpmyadmin and marialdb version information is like this.
Let me know if anyone here can help me for same
Thanks!

This is a PhpMyAdmin bug. You need to upgrade to 5.5.0 to get the fix.

Related

Display all data grouped by date in a particular timeframe

Currently I have 2 tables, a listing table and a logs table. With the following query I'm trying to get the listings of a product on a particular day, and it returns the right output.
with X as (
select
l.*,
(select status_from from logs where logs.refno = l.refno and logs.logtime >= '2021-10-01' order by logs.logtime limit 1) logstat
from listings l
where l.added_date < '2021-10-01'
)
, Y as (select X.*, ifnull(X.logstat, X.status) stat from X)
SELECT
status.text,
COUNT(Y.id) AS c
from status
left join Y on Y.stat = status.code
group by status.code, status.text;
This gives an output like this:
Here I've filtered the query by 1 date which in this case is 2021-10-01. Now I have 2 input forms where the user can select a from date and a to date. So I want to be able to get all the data between the date range provided. So basically if I choose a date between 2021-10-01 and 2021-10-02, it should show everything on and between that date. The output should look like:
Date
Publish
Action
Let
Sold
Draft
2021-10-01
0
3
0
1
1
2021-10-02
0
2
0
1
2
Dbfiddle: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=5e0b8d484a41ac9104d0fb002e7f9a3c
I've formatted the table to show the entries in a row wise manner with the following query:
with X as (
select l.*,
(select status_from from logs where logs.refno = l.refno and logs.logtime >= '2021-10-01' order by logs.logtime limit 1) logstat
from listings l
where l.added_date < '2021-10-01'
)
, Y as (select X.*, ifnull(X.logstat, X.status) stat20211001 from X)
SELECT
sum(case when status.text= 'Action' and Y.id is not null then 1 else 0 end) as `Action`,
sum(case when status.text= 'Draft' and Y.id is not null then 1 else 0 end) as `Draft`,
sum(case when status.text= 'Let' and Y.id is not null then 1 else 0 end) as `Let`,
sum(case when status.text= 'Sold' and Y.id is not null then 1 else 0 end) as `Sold`,
sum(case when status.text= 'Publish' and Y.id is not null then 1 else 0 end) as `Publish`
from status
left join Y on Y.stat20211001 = status.code
Output for this statement:
If you open my dbfiddle and enter date as 2021-10-01 it gives correct output and if you enter 2021-10-02 it shows correct output. Now I just want a way to show these both together. Also if it is suppose 2021-10-01 and 2021-10-05, it should show everything in middle too which means 2021-10-01, 2021-10-02, 2021-10-03, 2021-10-04 and 2021-10-05
Your listings.added_date column has the DATETIME data type. Therefore, to select a date range of 2021-10-01 to 2021-10-02 you need to do this.
WHERE added_date >= '2021-10-01'
AND added_date < '2021-10-02' + INTERVAL 1 DAY
This pulls in all the rows from midnight on 1-October, up to but not including midnight on 3-October.
If you want to aggregate your results by day, you can use GROUP BY DATE(added_date).
A sample query -- to show all days in September -- might look like this:
SELECT DATE(added_date) day,
SUM(CASE WHEN status.text= 'Action' THEN 1 ELSE 0 END) AS `Action`,
SUM(CASE WHEN status.text= 'Draft' THEN 1 ELSE 0 END) AS `Draft`,
SUM(CASE WHEN status.text= 'Let' THEN 1 ELSE 0 END) AS `Let`
FROM tbl
WHERE added_date >= '2021-09-01'
AND added_date < '2021-09-01' + INTERVAL 1 MONTH
GROUP BY DATE(added_date);
Sorry to say, I don't understand how your sample query works well enough to rewrite it with GROUP BY. But this should get you started.

Mysql 'greater than(>)' query always returns 0

I am working with a query where I want to display number of upcoming dates. The following query returns 0 even though there are dates greater than current date. Please help me to solve this problem.
SELECT (case when b.booked_date > cast(now() as date) then sum(1) else sum(0) end) as upcoming_booked_facilities
from svk_apt_book_facilities b
where b.customer_id = 1
and b.association_id = 1
and b.is_active = 1
group by b.facility_id
You need to sum a CASE expression to do conditional aggregation:
SELECT
facility_id,
SUM(CASE WHEN booked_date > CURDATE() THEN 1 ELSE 0 END) AS upcoming_booked_facilities
FROM svk_apt_book_facilities
WHERE
customer_id = 1 AND
association_id = 1 AND
is_active = 1
GROUP BY
facility_id;
You were trying to use the sum as the predicate of the CASE expression, which is probably not what you want. Note that I am also selecting the facility_id, since you are grouping by that column. If you instead want a conditional sum over the entire table, then don't select or group by facility.

Mysql group by date and count query

I have table as below :-
With help of MySql query, I want result as below:
date total read unread
2018-01-31 8 4 4
2018-02-01 2 2 0
Try this:
SELECT date, COUNT(*) as total,
SUM(CASE WHEN read = 1 THEN 1 ELSE 0) as read
SUM(CASE WHEN read = 0 THEN 1 ELSE 0) as unread
FROM yourtable
GROUP BY date
you can use case for aggregate the filtered value for read
select date
, count(*), sum(case when read=1 then 1 else 0 end ) as read
, sum(case when read=0 then 1 else 0 end ) as unread
from my_table
group by date
Try This we don't need case in the read column as 1 means read so we simply sum the value. It will help in the performance if we are dealing with the huge data:
SELECT date,
COUNT(*) as total,
SUM(read) as read --Case not needed here
SUM(CASE WHEN read = 0 THEN 1 ELSE 0) as unread
FROM yourtable
GROUP BY date
You have to group rows by date using group by, then you can use count to count the total number of rows within each date group (= total column).
In order to obtain the number of read and unread, you can sum read and unread value
SELECT date
, COUNT(*) AS total
, SUM(READ) AS READ
, SUM(CASE WHEN READ = 0 THEN 1 ELSE 0 END) AS unread
FROM mytable
GROUP BY date

SQL query summary issue

I'm new to SQL and trying to create a total summary of a working SQL query. It's listing the total results from one month of data.
Now I need the total values of the outcome of the query.
So I created a 'query in a query' piece of SQL, but it ain't working because my lack of SQL knowledge. I guess it's an easy fix for you pro's :-)
The working SQL query with the daily outcome of one month:
SELECT
DATE_FORMAT(date, '%d/%m/%y') AS Datum,
COUNT(*) AS Berichten,
SUM(CASE WHEN virusinfected>0 THEN 1 ELSE 0 END) AS Virus,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND isspam>0 THEN 1 ELSE 0 END) AS Ongewenst,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND (isspam=1) AND isrblspam>0 THEN 1 ELSE 0 END) AS RBL,
SUM(size) AS Grootte
FROM
maillog
WHERE
1=1
AND (1=1)
AND
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain1.nl'
OR
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain2.nl'
GROUP BY
Datum
ORDER BY
date
The incorrect query trying to create the monthly totals:
SELECT Datum,
SUM(Berichten) AS Berichten,
SUM(Virus) AS Virus,
SUM(Ongewenst) AS Ongewenst,
SUM(RBL) AS RBL,
SUM(Grootte) AS Grootte,
FROM ( SELECT
DATE_FORMAT(date, '%d/%m/%y') AS Datum,
COUNT(*) AS Berichten,
SUM(CASE WHEN virusinfected>0 THEN 1 ELSE 0 END) AS Virus,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND isspam>0 THEN 1 ELSE 0 END) AS Ongewenst,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND (isspam=1) AND isrblspam>0 THEN 1 ELSE 0 END) AS RBL,
SUM(size) AS Grootte
FROM
maillog
WHERE
1=1
AND (1=1)
AND
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain1.nl'
OR
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain2.nl'
GROUP BY
Datum
ORDER BY
date
) t
GROUP BY Datum;
Thanks in advance.
What you want can be done with just a little addition to your first SQL statement: add with rollup after the group by clause:
GROUP BY Datum WITH ROLLUP
It will run more efficiently than the version with sub-query, although it could work that way, but you should then remove the outer group by clause and not select Datum there, since you don't want the totals per date any more, but overall.
Still, you will lose the details and only get the overall totals then. You would have to use a union with your original query to get both levels of totals. You can imagine that the with rollup modifier will do the job more efficiently.

Sales and transaction totals by part, grouped by last 24 months

SELECT det.partNum,
SUM(det.quantity) AS Demand1,
COUNT(det.partNum) AS Call1
FROM details det
JOIN invoice inv ON det.invoice_id = inv.id
WHERE inv.invoice_date
BETWEEN '2015-11-01 00:00:00'
AND '2015-11-31 23:59:59'
GROUP BY partNum
The above sql returns all part numbers, the total number sold (Demand), and the total number of transactions the parts were involved in (Call) for the current month.
What our vendor wants is this information for every part, but also grouped for each of the past 24 months. The csv they are requesting would look like the following (if only viewing the last 3 months):
Part# | Demand1 | Demand2 | Demand3 | Call1 | Call2 | Call3
123 | 0 | 2 | 0 | 0 | 1 | 0
345 | 6 | 3 | 4 | 1 | 2 | 3
Part# 123: 0 transactions this month (Call1) 0 quantity sold (Demand1)
1 transaction last month (Call2) 2 quantity sold (Demand2).
0 transactions two months ago (Call3) 0 quantity sold (Demand3).
Part# 345: 1 transaction this month (Call1) for qty sold of 6 (Demand1)
2 transactions last month (Call2) for qty sold of 3 (Demand2)
3 transactions two months ago (Call3) for qty sold of 4 (Demand3)
Realize that they want this extended out for the past 24 months. Demand1/Call1 are always the current month.
I used the WHERE/BETWEEN statement to show where the date is coming from and to demonstrate how I can get an accurate report of the parts for the current month.
What I can't figure out how to do is to fill Demand and Call for 24 months. And this is the format that the vendor expects the data to be in. This wasn't my choice. Any help in getting this working as expected would be greatly appreciated.
Thanks
EDIT
I removed the sql-server tag. Sorry about that. This is only MySQL.
Also, I'm adding my reply from below...
Looking into DATEDIFF, TIMESTAMPDIFF, and even PERIOD_DIFF. But none actually seem to return what I need. What needs to happen is the first demand column should search for the current month, day 1 (inclusive) through the next month, day 1 (exclusive). The next demand column should search the current month - one month, day 1 (inclusive) through next month - one month, day 1 (exclusive). And each subsequent column should search the same parameters, subtracting an additional month each column. I don't think that can be accomplished with precision simply using DATEDIFF.
I hope that makes sense.
And again, thanks for any help.
If I understood your problem correctly, you can do it like this:
SELECT
det.partNum,
SUM(case when inv.invoice_date >= dateadd(month, -3, #currMonth) and inv.invoice_date < dateadd(month, -2, #currMonth) then det.quantity else 0) AS Demand1,
SUM(case when inv.invoice_date >= dateadd(month, -2, #currMonth) and inv.invoice_date < dateadd(month, -1, #currMonth) then det.quantity else 0) AS Demand2,
...
FROM details det
JOIN invoice inv ON det.invoice_id = inv.id
WHERE
inv.invoice_date >= '2015-11-01 00:00:00' AND inv.invoice_date < '2015-12-01'
GROUP BY partNum
This uses a variable that has the start date of current month to make the SQL more simple. I also changed the where clause, you should really use >= + < with dates instead of between.
This might get you started with Pivot query.
;WITH cte AS
(
SELECT det.partNum,
SUM(det.quantity) AS DemandSum,
COUNT(det.partNum) AS CallCount,
DATEDIFF(MONTH,inv.invoice_date, GETDATE()) + 1 MonthDiff
FROM details det
JOIN invoice inv ON det.invoice_id = inv.id
GROUP BY det.partNum, DATEDIFF(MONTH,inv.invoice_date, GETDATE()) + 1
)
SELECT t.partNum,
[Demand1],[Demand2],[Demand3],[Demand4],[Demand5],[Demand6],[Demand7],[Demand8],[Demand9],[Demand10],[Demand11],[Demand12],
[Demand13],[Demand14],[Demand15],[Demand16],[Demand17],[Demand18],[Demand19],[Demand20],[Demand21],[Demand22],[Demand23],[Demand24],
[Call1],[Call2],[Call3],[Call4],[Call5],[Call6],[Call7],[Call8],[Call9],[Call10],[Call11],[Call12],
[Call13],[Call14],[Call15],[Call16],[Call17],[Call18],[Call19],[Call20],[Call21],[Call22],[Call23],[Call24]
FROM (SELECT DISTINCT partNum FROM cte) t
LEFT JOIN (
SELECT * FROM (
SELECT partNum, DemandSum, CONCAT('Demand',MonthDiff) ColName FROM cte
) c PIVOT (SUM(DemandSum) FOR ColName IN ([Demand1],[Demand2],[Demand3],[Demand4],[Demand5],[Demand6],[Demand7],[Demand8],[Demand9],[Demand10],[Demand11],[Demand12],
[Demand13],[Demand14],[Demand15],[Demand16],[Demand17],[Demand18],[Demand19],[Demand20],[Demand21],[Demand22],[Demand23],[Demand24])
) p
) ds ON ds.partNum = t.partNum
LEFT JOIN (
SELECT * FROM (
SELECT partNum, CallCount, CONCAT('Call',MonthDiff) ColName FROM cte
) c PIVOT (COUNT(CallCount) FOR ColName IN ([Call1],[Call2],[Call3],[Call4],[Call5],[Call6],[Call7],[Call8],[Call9],[Call10],[Call11],[Call12],
[Call13],[Call14],[Call15],[Call16],[Call17],[Call18],[Call19],[Call20],[Call21],[Call22],[Call23],[Call24])
) p
) cc ON cc.partNum = t.partNum
if that's too confusing, you can use the CASE method. I'd do it a little different than the other answer though..
SELECT
det.partNum,
SUM(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 0 then det.quantity else 0 end) AS Demand1,
SUM(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 1 then det.quantity else 0 end) AS Demand2,
SUM(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 2 then det.quantity else 0 end) AS Demand3,
COUNT(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 0 then det.partNum end) AS Call1,
COUNT(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 1 then det.partNum end) AS Call2,
COUNT(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 2 then det.partNum end) AS Call3
FROM
details det
JOIN invoice inv ON det.invoice_id = inv.id
GROUP BY
det.partNum
you can get the full script for all 24 months here.. SQL Fiddle