MySQL easy question CURDATE() - datetime

I want to compare two results
one is stored in the first query, and the other is exactly the same as the first, but i want only to recieve data < today
"SELECT s.GSP_nom as nom, timestamp, COUNT(s.GSP_nom) as nb_votes, AVG(v.vote+v.prix+v.serviceClient+v.interface+v.interface+v.services)/6 as moy
FROM votes_serveur AS v
INNER JOIN serveur AS s ON v.idServ = s.idServ
WHERE s.valide = 1
AND v.date < CURDATE()
GROUP BY s.GSP_nom
HAVING nb_votes > 9
ORDER BY moy DESC LIMIT 0,15";
is that correct ?
thank you

GROUP BY, not ROUP BY
v.date < CURDATE() looks o.k.

Related

mariadb alternative to outer apply or lateral?

What I wanted was to use CROSS APPLY, but I guess that doesn't exist in mysql. The alternative I've read is LATERAL. Well, I'm using mariadb 10.3 and I guess that doesn't exist either. The ticket table contains an id that's referenced by the ticket_id column in the note table. A ticket can have many notes, I'm trying to list all tickets with their most recent note date (post_date). How could I write the query below for mariadb?
SELECT t.*, n.post_date
FROM ticket t,
LATERAL (
SELECT note.post_date FROM note WHERE t.id = note.ticket_id ORDER BY note.post_date DESC LIMIT 1
) n;
Example table structure:
Ticket
id
subject
1
stuff
2
more
note
id
post_date
ticket_id
1
1
2
1
3
2
4
1
5
2
I did find an open jira ticket from people asking for mariadb to support lateral.
From what I read, LATERAL will not be supported in MariaDB until version 11. But we can just as easily use ROW_NUMBER here, which is supported:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY ticket_id ORDER BY post_date DESC) rn
FROM note
)
SELECT t.*, n.post_date
FROM ticket t
INNER JOIN cte n
ON n.ticket_id = t.id
WHERE n.rn = 1;
If you wanted a close translation of your current lateral join, then use:
SELECT t.*,
(SELECT n.post_date
FROM note n
WHERE t.id = note.ticket_id
ORDER BY n.post_date DESC
LIMIT 1)
FROM ticket t;

SQLITE query GROUP BY with SUM Using Delphi and Zeos

I have an app created using Delphi XE3 accessing the SQLite database with Zeos Component.
A select command in SQLite that return 3 rows:
select p.descricao, pg.valor
from pagamento pg
inner join venda v on pg.origem = 'venda' and v.id_venda = pg.id_origem
left join pagamento_tipo p on pg.id_pagamento_tipo = p.id_pagamento_tipo
where v.data >= '2021-01-19' and v.data <= '2021-01-19'
and v.ra_status_venda in ( 'Finalizado', 'Pedido')
but when I put the group command the information result is wrong.
select p.descricao, sum(pg.valor) as valor
from pagamento pg
inner join venda v on pg.origem = 'venda' and v.id_venda = pg.id_origem
left join pagamento_tipo p on pg.id_pagamento_tipo = p.id_pagamento_tipo
where v.data >= '2021-01-19' and v.data <= '2021-01-19'
and v.ra_status_venda in ( 'Finalizado', 'Pedido')
group by descricao
the P02 not sum.
and, if I sum all row, without group by, the value was correct too.
select sum(pg.valor) as valor
from pagamento pg
inner join venda v on pg.origem = 'venda' and v.id_venda = pg.id_origem
left join pagamento_tipo p on pg.id_pagamento_tipo = p.id_pagamento_tipo
where v.data >= '2021-01-19' and v.data <= '2021-01-19'
and v.ra_status_venda in ( 'Finalizado', 'Pedido')
PS: in another period this commands sum correctly.
PS2 I'm using dll 32bits for windows.
With tips #Shawn and #forpas I solve this problem, the SQLite type of field NUMERIC converts the numbers to other types in the RUNTIME select command, how the two first values were INTEGER and the last value were Real, apparently my program not recognize two different types in the same column.
To solve I change the type of field in the database from NUMERIC to REAL.

Update Rows based on JOIN results

I can't get the following query to work:
UPDATE ISSUE
SET DUE_DATE = DATE(ISSUE.DATE_ADDED,'+90 day')
JOIN CVE on CVE.CVE_ID = ISSUE.CVE_ID
WHERE CVE.CVSS >= 4 AND CVE.CVSS < 9
This is because in sqlite3 you can't join in an UPDATE. What I'm trying to do is set the due date of an issue to be 90 days after the date added if the CVE associated with the issue is: greater than or equal to four and less than 9. Is there an alternative option that I'm missing here?
You can join the rows in a sub-query.
UPDATE ISSUE
SET DUE_DATE = DATE(ISSUE.DATE_ADDED,'+90 day')
WHERE ISSUE.CVE_ID IN (
SELECT ISSUE.CVE_ID
FROM ISSUE JOIN CVE on CVE.CVE_ID = ISSUE.CVE_ID
WHERE CVE.CVSS >= 4 AND CVE.CVSS < 9
)

Translate SQLite query, with subquery, into Peewee statement

I've got a SQL statement that does what I need, but I'm having trouble converting it into the correlated Peewee statement. Here's the SQL I have now, note that I'm using a subquery right now, but I don't care that it's a subquery either way.
select t.name,
count(a.type_id) as total,
(
select count(id)
from assignment a
where a.course_id = 7
and a.due_date < date()
and a.type_id = t.id
group by a.type_id
order by a.type_id
) as completed
from assignment a
inner join type t on t.id = a.type_id
where a.course_id = 7
group by a.type_id
order by a.type_id
Here's the closest I've come to the Peewee statement. Currently I'm aliasing a static number in the query just so that I have a value to work with in my template, so please ignore that part.
Assignment.select(
Type.name,
fn.Lower('1').alias('completed'),
fn.Count(Type.id).alias('total'),
).naive().join(Type).where(
Assignment.course==self,
).group_by(Type.id).order_by(Type.id)
Have you tried just including the subquery as part of the select?
Something like this?
query = (Assignment
.select(
Type.name,
fn.COUNT(Type.id).alias('total'),
Assignment.select(fn.COUNT(Assignment.id)).where(
(Assignment.due_date < fn.DATE()) &
(Assignment.course == 7) &
(Assignment.type == Type.id)
).group_by(Assignment.type).alias('completed'))
.join(Type)
.where(Assignment.course == 7)
.group_by(Type.name))

Retrieve a table to tallied numbers, best way

I have query that runs as part of a function which produces a one row table full of counts, and averages, and comma separated lists like this:
select
(select
count(*)
from vw_disp_details
where round = 2013
and rating = 1) applicants,
(select
count(*)
from vw_disp_details
where round = 2013
and rating = 1
and applied != 'yes') s_applicants,
(select
LISTAGG(discipline, ',')
WITHIN GROUP (ORDER BY discipline)
from (select discipline,
count(*) discipline_number
from vw_disp_details
where round = 2013
and rating = 1
group by discipline)) disciplines,
(select
LISTAGG(discipline_count, ',')
WITHIN GROUP (ORDER BY discipline)
from (select discipline,
count(*) discipline_count
from vw_disp_details
where round = 2013
and rating = 1
group by discipline)) disciplines_count,
(select
round(avg(util.getawardstocols(application_id,'1','AWARD_NAME')), 2)
from vw_disp_details
where round = 2013
and rating = 1) average_award_score,
(select
round(avg(age))
from vw_disp_details
where round = 2013
and rating = 1) average_age
from dual;
Except that instead of 6 main sub-queries there are 23.
This returns something like this (if it were a CSV):
applicants | s_applicants | disciplines | disciplines_count | average_award_score | average_age
107 | 67 | "speed,accuracy,strength" | 3 | 97 | 23
Now I am programmatically swapping out the "rating = 1" part of the where clauses for other expressions. They all work rather quickly except for the "rating = 1" one which takes about 90 seconds to run and that is because the rating column in the vw_disp_details view is itself compiled by a sub-query:
(SELECT score
FROM read r,
eval_criteria_lookup ecl
WHERE r.criteria_id = ecl.criteria_id
AND r.application_id = a.lgo_application_id
AND criteria_description = 'Overall Score'
AND type = 'ABC'
) reader_rank
So when the function runs this extra query seems to slow everything down dramatically.
My question is, is there a better (more efficient) way to run a query like this that is basically just a series of counts and averages, and how can I refactor to optimize the speed so that the rating = 1 query doesn't take 90 seconds to run.
You could choose to MATERIALIZE the vw_disp_details VIEW. That would pre-calculate the value of the rating column. There are various options for how up-to-date a materialized view is kept, you would probably want to use the ON COMMIT clause so that vw_disp_details is always correct.
Have a look at the official documentation and see if that would work for you.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6002.htm
Do all most of your queries in only one. Instead of doing:
select
(select (count(*) from my_tab) as count_all,
(select avg(age) from my_tab) as avg_age,
(select avg(mypkg.get_award(application_id) from my_tab) as_avg-app_id
from dual;
Just do:
select count(*), avg(age),avg(mypkg.get_award(application_id)) from my_tab;
And then, maybe you can do some union all for the other results. But this step all by itself should help.
I was able to solve this issue by doing two things: creating a new view that displayed only the results I needed, which gave me marginal gains in speed, and in that view moving the where clause of the sub-query that caused the lag into the where clause of the view and tacking on the result of the sub-query as column in the view. This still returns the same results thanks to the fact that there are always going to be records in the table the sub-query accessed for each row of the view query.
SELECT
a.application_id,
util.getstatus (a.application_id) status,
(SELECT score
FROM applicant_read ar,
eval_criteria_lookup ecl
WHERE ar.criteria_id = ecl.criteria_id
AND ar.application_id = a.application_id
AND criteria_description = 'Overall Score' //THESE TWO FIELDS
AND type = 'ABC' //ARE CRITERIA_ID = 15
) score
as.test_total test_total
FROM application a,
applicant_scores as
WHERE a.application_id = as.application_id(+);
Became
SELECT
a.application_id,
util.getstatus (a.application_id) status,
ar.score,
as.test_total test_total
FROM application a,
applicant_scores as,
applicant_read ar
WHERE a.application_id = as.application_id(+)
AND ar.application_id = a.application_id(+)
AND ar.criteria_id = 15;

Resources