Im trying to use a variable to count the number of rows i have for a specific id, if i use it without inner joins it works perfectly, otherwise no, here is the section without joins
select
cd.basis_point bpt,
cd.created,
#version:=#version+1 version
from tbl_class_det cd, (select #version:=1) v
where (cd.class_uuid='{$row['uuid']}')
and (cd.created>(
select
created
from tbl_class_det
where (class_uuid=cd.class_uuid)
order by created asc
limit 1
))
order by cd.created asc
the section with joins that gives an error:
select c.name,
fd.value bpt,
fd.created,
#version:=#version+1 version
from tbl_fee_det fd, (select #version:=1) v
INNER JOIN tbl_fee f ON f.uuid = fd.fee_uuid
INNER JOIN tbl_class c ON c.uuid = f.class_uuid
where (fd.created>(
select
created
from tbl_class_det
where (fee_uuid=f.uuid)
order by created asc
limit 1
))
order by fd.created asc;
You are using a combination of explicit and implicit joins. You should not mix the JOIN syntax with the comma syntax. If you need to you this then use a subquery similar to this:
select name,
value bpt,
created,
#version:=#version+1 version
from
(
select c.name,
fd.value,
fd.created,
f.uuid
FROM tbl_fee_det fd
INNER JOIN tbl_fee f
ON f.uuid = fd.fee_uuid
INNER JOIN tbl_class c
ON c.uuid = f.class_uuid
) f, (select #version:=1) v
where (created>(select created
from tbl_class_det
where (fee_uuid=f.uuid)
order by created asc
limit 1))
order by created asc;
Related
I have the SQL command:
SELECT
vinculo.id,
data start,
count(*) title
from
atendimento_regulacao
join vinculo on vinculo.id = atendimento_regulacao.vinculo_id
where data = '2019-07-02'
group by vinculo.usuario_id, atendimento_regulacao.data
The result is empty because not exists none record on where data = '2019-07-02'
How to show the id like below?
id | start | title
1 | |
You can use a CROSS JOIN to generate the rows and LEFT JOIN to bring in the results:
select v.id, d.dte as start, count(ar.vinculo_id) as num_title
from (select '2019-07-02' as dte) d cross join
vinculo v left join
atendimento_regulacao ar
on v.id = ar.vinculo_id and ar.data = d.dte
group by v.id, d.dte;
If you really want to aggregate by v.usuario_id, then include it in both the select and group by.
Notes:
The structure of the query easily extends to multiple dates.
The GROUP BY uses the same columns in the SELECT.
Table aliases make the query easier to write and to read.
Qualify all column references in a query that has more than one table reference.
The COUNT() uses a column from ar so it can return 0.
For the specific case of a single date, you can use conditional aggregation:
select v.id, '2019-07-02' as start,
count(ar.vinculo_id) as num_title
from vinculo v left join
atendimento_regulacao ar
on v.id = ar.vinculo_id and ar.data = '2019-07-02'
group by v.id;
Use RIGHT JOIN, and convert your count to the one below, otherwise it shows zero whenever didn't find to count anything.
SELECT v.id, a.data start,
case when count(*) is null then null end title
FROM atendimento_regulacao a
RIGHT JOIN vinculo v
ON v.id = a.vinculo_id
AND a.data = '2019-07-02'
GROUP BY v.usuario_id, a.data;
Demo
What I am trying to do it with below code, getting all keywords with their positions via LEFT JOIN, it works fine but it shows the first position of each keyword, but I want to show the last position that recorded (by date).
SELECT keyword.id, keyword.title, keyword.date, rank.position FROM keyword
LEFT JOIN rank
ON rank.wordid = keyword.id
GROUP BY keyword.id
ORDER BY keyword.date DESC
How can I do this? Should I use subquery or what? Is there any way to do this without a subquery?
SAMPLE DATA
What I want:
Get 17 instead of 13, I mean last record of position.
Do not use group by for this! You want to filter, so use a where clause. In this case, using a correlated subquery works well:
SELECT k.id, k.title, k.date, r.position
FROM keyword k LEFT JOIN
rank r
ON r.wordid = k.id AND
r.date = (SELECT MAX(r2.date)
FROM rank r2
WHERE r2.wordid = k.id
)
ORDER BY k.date DESC
You can use below query
SELECT keyword.id, keyword.title, keyword.date, rankNew.position FROM keyword LEFT JOIN (
SELECT rank.wordid, rank.position FROM rank ORDER BY rank.id DESC LIMIT 0, 1) AS rankNew ON (rankNew.wordid = keyword.id);
You can get more reference from Retrieving the last record in each group - MySQL
I have a table, named rendeles_termekek.(In english, ordered_products)
I would like to count, that each product how many times was ordered.
With the SQL below, I get 4 as ennyi. I upload a picture, and I wrote the correct number to each rows.
SELECT DISTINCT
rendeles_termekek.termek_id,
termek.termek_id,
termek.termek_nev,
( SELECT COUNT(rendeles_termekek.termek_id) FROM rendeles_termekek ) AS ennyi
FROM rendeles_termekek
LEFT JOIN termek ON rendeles_termekek.termek_id = termek.termek_id
ORDER BY termek.termek_nev ASC
**r1** is the alias of your table rendeles_termekek so you have to access those columns through alias name "r1" like I did in below query. try below
SELECT DISTINCT
r1.termek_id,
termek.termek_id,
termek.termek_nev,
( SELECT COUNT(r.termek_id) FROM rendeles_termekek r where r.termek_id = r1.termek_id ) AS ennyi
FROM rendeles_termekek r1
LEFT JOIN termek ON r1.termek_id = termek.termek_id
ORDER BY termek.termek_nev ASC
I think you have only four rows in your table "rendeles_termekek".
I have updated your query. try this
SELECT DISTINCT
rendeles_termekek.termek_id,
termek.termek_id,
termek.termek_nev,
( SELECT COUNT(rendeles_termekek.termek_id) FROM rendeles_termekek r where r.termek_id = r1.termek_id ) AS ennyi
FROM rendeles_termekek r1
LEFT JOIN termek ON rendeles_termekek.termek_id = termek.termek_id
ORDER BY termek.termek_nev ASC
Note that I have changed the sub-query and added a where condition in it
`( SELECT COUNT(rendeles_termekek.termek_id) FROM rendeles_termekek r where r.termek_id = r1.termek_id ) AS ennyi`
I am trying to bring through the site.Site_Name, for each hive.hiveno and it's max(hiverdg.invdate). Running the code below doesn't work because site.Site_Name is not aggrigated. If I add site.Site_Name to the Group By, the code runs, but the ouput displays the results repeated, once for each site.Site_Name
select site.Site_Name ,hive.hiveno, max(hiverdg.invdate)
from hiverdg
inner join hive
on hiveRdg.hive_Link = hive.hive_Link
inner join Customer
on customer.Customer_Link = hive.Customer_Link
inner join site
on site.Customer_Link = customer.Customer_Link
where
(hiverdg.xtype = 'N'
and customer.CustomerName = 'Cust1')
or
(hiverdg.xtype = 'A'
and customer.CustomerName = 'Cust1')
group by hive.hiveno
The easiest way to do this, with your query, is the substring_index()/group_concat() trick:
select substring_index(group_concat(s.Site_Name order by rdg.invdate desc separator '|'
), '|', 1
) as SiteName,
h.hiveno, max(rdg.invdate)
from hiverdg rdg inner join
hive h
on rdg.hive_Link = h.hive_Link inner join
Customer c
on c.Customer_Link = h.Customer_Link inner join
site s
on s.Customer_Link = c.Customer_Link
where rdg.xtype in ('N', 'A') and c.CustomerName = 'Cust1')
group by h.hiveno;
I also made the following changes to your query:
Introduced table aliases, to make the query easier to write and to read.
Changed the where to use in, simplifying the logic.
I have the following query, but after some time when users start putting in more and more items in the "ci_falsepositives" table, it gets really slow.
The ci_falsepositives table contains a reference field from ci_address_book and another reference field from ci_matched_sanctions.
How can I create a new query but still being able to sort on each field.
For example I can still sort on "hits" or "matches"
SELECT *, matches - falsepositives AS hits
FROM (SELECT c.*, IFNULL(p.total, 0) AS matches,
(SELECT COUNT(*)
FROM ci_falsepositives n
WHERE n.addressbook_id = c.reference
AND n.sanction_key IN
(SELECT sanction_key FROM ci_matched_sanctions)
) AS falsepositives
FROM ci_address_book c
LEFT JOIN
(SELECT addressbook_id, COUNT(match_id) AS total
FROM ci_matched_sanctions
GROUP BY addressbook_id) AS p
ON c.id = p.addressbook_id
) S
ORDER BY folder asc, wholename ASC
LIMIT 0,15
The problem has to be the SELECT COUNT(*) FROM ci_falsepositives sub-query. That sub-query can be written using an inner join between ci_falsepositives and ci_matched_sanctions, but the optimizer might do that for you anyway. What I think you need to do, though, is make that sub-query into a separate query in the FROM clause of the 'next query out' (that is, SELECT c.*, ...). Probably, that query is being evaluated multiple times - and that's what's hurting you when people add records to ci_falsepositives. You should study the query plan carefully.
Maybe this query will be better:
SELECT *, matches - falsepositives AS hits
FROM (SELECT c.*, IFNULL(p.total, 0) AS matches, f.falsepositives
FROM ci_address_book AS c
JOIN (SELECT n.addressbook_id, COUNT(*) AS falsepositives
FROM ci_falsepositives AS n
JOIN ci_matched_sanctions AS m
ON n.sanction_key = m.sanction_key
GROUP BY n.addressbook_id
) AS f
ON c.reference = f.addressbook_id
LEFT JOIN
(SELECT addressbook_id, COUNT(match_id) AS total
FROM ci_matched_sanctions
GROUP BY addressbook_id) AS p
ON c.id = p.addressbook_id
) AS s
ORDER BY folder asc, wholename ASC
LIMIT 0, 15