Table 1: mappingtable (this contains the tags mapping with sentence)
id tag_id sentence_id
1 10 30
2 11 40
Table 2 reports
sentence_id DATE property (sentences may repeat)
30 timestamp1 property1
30 timestamp2 property2
40 timestamp3 property1
I am trying to get the tag ids and count of tags grouped by time.
I tried this query
SELECT DISTINCT(tag_id),COUNT(tag_id) AS cnt, MONTH(DATE) AS mnt
FROM mappingtable
INNER JOIN reports
ON mappingtable .sentence_id=reports.sentence_id AND reports.property= 'property1' GROUP BY tag_id,mnt ORDER BY cnt DESC;
However if the sentence repeats in the reports table (as is usually the case) the count of tags is coming wrong.
Edit:
EDIT
Tried the query suggested below:
SELECT M.tag_id, COUNT(M.tag_id) AS cnt, MONTH(R.DATE) AS mnt FROM mappingtable M INNER JOIN reports R ON M.sentence_id = R.sentence_id AND R.property = 'property1' GROUP BY M.tag_id, MONTH(R.DATE) ORDER BY COUNT(M.tag_id) DESC;
Even this query is giving additional counts because of repeating sentence ids.
What I need is the unique sentences for property property1 grouped by month and then the tags counts of those sentences.
tag_id cnt mnt
60865 145 11
60869 99 11
60994 74 11
61163 74 11
Something like this:
SELECT
M.tag_id,
COUNT(M.tag_id) AS cnt,
MONTH(R.DATE) AS mnt
FROM mappingtable M
INNER JOIN reports R
ON M.sentence_id = R.sentence_id
AND R.property = 'property1'
GROUP BY M.tag_id,
MONTH(R.DATE)
ORDER BY COUNT(M.tag_id) DESC;
The inner join would take the records common to both tables. I believe thats why you are getting a wrong count of tags. Even if a sentence has two properties, there would be just one occurrence in the join.
Related
I am developing a WordPress website for e learning. So one student attends the course, many times and scored the mark many times. Now I need to get one id with score and last record. I have tried many examples, but am able to get the result. I have given below my code.
SELECT m.id
, m.email
, t.id_tracking
, t.user_id
, FROM_UNIXTIME(t.date)
, t.score
, t.groupe_id
FROM tracking t
join membres m
WHERE t.id_tracking IN (
SELECT MAX(date)
FROM tracking
GROUP BY user_id
)
I have used about the query I don't know what I did wrong
user_id email score date
1 test#testmail.com 78 15-06-2019
1 test#testmail.com 89 12-08-2019
2 sam#testmail.com 66 24-03-2018
2 sam#testmail.com 44 19-07-2019
3 siv#testmail.com 98 09-02-2019
3 siv#testmail.com 78 13-08-2020
I need to get result below like
user_id email score date
1 test#testmail.com 89 12-08-2019
2 sam#testmail.com 44 19-07-2019
3 siva#testmail.com 98 09-08-2020
You can GROUP BY email/user_id and select maximum of date from each group, by converting the date to a UNIX TIMESTAMP, like this
SELECT user_id, email, score, FROM_UNIXTIME(MAX(UNIX_TIMESTAMP(date)))
FROM tableName
GROUP BY user_id
I am not sure about your DB but,
Have you tried like this...
SELECT
*
FROM
(SELECT * FROM process_table ORDER BY date desc) tbl1
GROUP BY
tbl1.id
i have two tables having following structure
Table A
itemId categoryId orderDate
==========================================
1 23 2016-11-08
1 23 2016-11-12
1 23 2016-11-16
Table B have the structure
categoryId stock price
==========================================
23 500 600
However mine desired output should be as like
Result C
price stock orderdate qty
600 500 2016-11-08 (first order date) 3 (3 time appearance in first table)
Here is what i have tried so far
select b.price,b.stock from B b, A a
where b.categoryId = (
select a.categoryId
from A
GROUP BY categoryId
HAVING COUNT(categoryId)>1
)
and (a.orderdate = (
select MIN(orderdate)
from A
where categoryId = b.categoryId)
)
i have following result
price stock orderdate
600 500 2016-11-08
i have no idea how do find qty as it is appeared 3 times in first table.
I think you want the records in table a grouped by item id and category id, so include these two in your group by statement. Then the other columns you have to aggregate using MIN, MAX, AVG, SUM, etc. I use MIN which will give you the smallest number in the group for that particular column, although it shouldn't matter in this case whether you use MIN or MAX or AVG - it's all the same. Then COUNT(*) will just count the number of recrods in the group.
Also, joins are generally preferred over listing tables with commas.
SELECT a.itemid, a.categoryid, MIN(b.price), MIN(b.stock), min(a.orderdate), count(*) as qty
FROM a
INNER JOIN b ON a.categoryid = b.categoryid
GROUP BY a.itemid, a.categoryid
You also need to select COUNT(*)
how about use following sql
select min(price), min(stock), min(orderDate), COUNT(categoryId)
from A,B where A.categoryId = B.categoryId
GROUP by A.categoryId
You could create views for your subqueries and give them meaningful names e.g. CategoriesUsedInMultipleOrders, MostRecentOrderByCategory. This would 'optimize' you query by abstracting away complexity and making it easier for the human reader to understand.
This is the Query with the appropriate join method see Result:
SELECT B.price, B.stock, MIN( A.orderDate ) AS orderdate, COUNT( * ) AS qty
FROM TableA A, TableB B
WHERE A.categoryId = B.CategoryId
GROUP BY A.categoryId, B.price, B.stock
I have a table that looks roughly like this
Year Species Count
1979 A 0
1980 A 10
1981 A 4
1982 A 3
1979 B 0
1980 B 1
1981 B 2
1982 B 3
1979 C 9
1980 C 14
1981 C 2
1982 C 1
What i want is to return all Year, Species, Count for those species that have a total count (as in summed over all years) of 10 or more. so for a total count of 20 i would want it to just return
1979 C 9
1980 C 14
1981 C 2
1982 C 1
i played around with having but havent really gotten anything useful (total SQL beginner)
In MySQL, you can do this using aggregation and a join:
select t.*
from table t join
(select species, count(*) as cnt
from table
group by species
) s
on t.species = s.species
where s.cnt >= 10;
This is the easiesy. You already have the counts. Group on species and filter table on the results of the subquesy. You can get the same functionality with an exists or a join also.
SELECT
[YEAR]
,SPECIES
,[COUNT]
FROM TABLE
WHERE SPECIES IN (
SELECT SPECIES
FROM TABLE
GROUP BY SPECIES
HAVING SUM([COUNT]) > 20)
)
Adding some addtional explanation for BootstrapBill
Group by "makes multiple sets" for each unique value of the GROUP BY column. That allows the aggregate function SUM() act on only one set of the GROUP BY values at a time. HAVING is sort of like a WHERE clause for the GROUP BY statement that allows you to apply a predicate. The only fields allowed to be returned by a GROUP BY are the grouped column itself and the results of any aggregate function(s), you need to join back to or filter the original set to get the other columns your are targeting in the query.
And I apoligze, I did not see where the OP stated this was for MySql. The core concept is the same so I am leaving the answer. [] are MS SQL syntax for escaping the keywords COUNT and YEAR.
You'll want to use GROUP BY with the SUM() aggregate function and HAVING clause (similar to WHERE, but for groups instead of rows), combined with a self-join:
SELECT t1.`Year`, t1.`Species`, t1.`Count`
FROM mytable t1 INNER JOIN (
SELECT `Species`, SUM(`Count`)
FROM mytable
GROUP BY `Species`
HAVING SUM(`Count`) >= 20
) t2
ON t1.`Species` = t2.`Species`
I'm running contests on my website. Every contest could have multiple entries. I want to retrieve if only the MAX value of votes has a duplicate.
The table is as follows:
contest_id entry_id votes
1 1 50
1 2 34
1 3 50
2 4 20
2 5 55
3 6 53
I just need the query to show me that contest 1 has a duplicate MAX value without additional information.
I tried this but didn't work:
SELECT MAX(votes) from contest group by contest_id having count(votes) > 1
SELECT a.contest_ID
FROM contest a
INNER JOIN
(
SELECT contest_id, MAX(votes) totalVotes
FROM contest
GROUP BY contest_id
) b ON a.contest_ID = b.contest_ID AND
a.votes = b.totalvotes
GROUP BY a.contest_ID
HAVING COUNT(*) >= 2
SQLFiddle Demo
This finds the max votes value per contest and counts the entries with that number of votes.
It then displays contest with more than one hit.
SELECT contest_id
FROM contests
WHERE votes=(
SELECT MAX(votes) FROM contests c WHERE c.contest_id=contests.contest_id
)
GROUP BY contest_id
HAVING COUNT(*) > 1;
SQLfiddle for testing.
You could do it by first selecting the maximum number of votes for each contest ID in a subquery, and then joining against the results (demo on SQLFiddle):
SELECT contest_id, votes
FROM contest
JOIN (
SELECT contest_id, MAX(votes) AS votes
FROM contest GROUP BY contest_id
) AS foo USING (contest_id, votes)
GROUP BY contest_id
HAVING COUNT(*) > 1
The nice thing about doing it like this is that it's an independent subquery, so MySQL only needs to rub it once.
Ps. Yes, this is basically identical to JW's answer, but I figured I'd leave it up anyway to show the slightly different syntax I used for the join.
I have three tables here, that I'm trying to do a tricky combined query on.
Table 1(teams) has Teams in it:
id name
------------
150 LA Lakers
151 Boston Celtics
152 NY Knicks
Table 2(scores) has scores in it:
id teamid week score
---------------------------
1 150 5 75
2 151 5 95
3 152 5 112
Table 3(tickets) has tickets in it
id teamids week
---------------------
1 150,152,154 5
2 151,154,155 5
I have two queries that I'm trying to write
Rather than trying to sum these each time i query the tickets, I've added a weekly_score field to the ticket. The idea being, any time a new score is entered for the team, I could take that teams id, get all tickets that have that team / week combo, and update them all based on the sum of their team scores.
I've tried the following to get the results i'm looking for (before I try and update them):
SELECT t.id, t.teamids, (
SELECT SUM( s1.score )
FROM scores s1
WHERE s1.teamid
IN (
t.teamids
)
AND s1.week =11
) AS score
FROM tickets t
WHERE t.week =11
AND (t.teamids LIKE "150,%" OR t.teamids LIKE "%,150")
Not only is the query slow, but it also seems to not return the sum of the scores, it just returns the first score in the list.
Any help is greatly appreciated.
If you are going to match, you'll need to accommodate for the column only having one team id. Also, you'll need to LIKE in your SELECT sub query.
SELECT t.id, t.teamids, (
SELECT SUM( s1.score )
FROM scores s1
WHERE
(s1.teamid LIKE t.teamids
OR CONCAT("%,",s1.teamid, "%") LIKE t.teamids
OR CONCAT("%",s1.teamid, ",%") LIKE t.teamids
)
AND s1.week =11
) AS score
FROM tickets t
WHERE t.week =11
AND (t.teamids LIKE "150,%" OR t.teamids LIKE "%,150" OR t.teamids LIKE "150")
You don't need SUM function here ? The scores table already has it? And BTW, avoid subqueries, try the left join (or left outer join depending on your needs).
SELECT t.id, t.name, t1.score, t2.teamids
FROM teams t
LEFT JOIN scores t1 ON t.id = t1.teamid AND t1.week = 11
LEFT JOIN tickets t2 ON t2.week = 11
WHERE t2.week = 11 AND t2.teamids LIKE "%150%"
Not tested.
Well not the most elegant query ever, but it should word:
SELECT
tickets.id,
tickets.teamids,
sum(score)
FROM
tickets left join scores
on concat(',', tickets.teamids, ',') like concat('%,', scores.teamid, ',%')
WHERE tickets.week = 11 and concat(',', tickets.teamids, ',') like '%,150,%'
GROUP BY tickets.id, tickets.teamids
or also this:
SELECT
tickets.id,
tickets.teamids,
sum(score)
FROM
tickets left join scores
on FIND_IN_SET(scores.teamid, tickets.teamids)>0
WHERE tickets.week = 11 and FIND_IN_SET('150', tickets.teamids)>0
GROUP BY tickets.id, tickets.teamids
(see this question and the answers for more informations).