I'm working on mysql and have two tables with the same schema:
preTrial
|id|accusedId|articleid|
------------------------
|1 | 1 | 1 |
|2 | 1 | 2 |
|3 | 1 | 3 |
|4 | 2 | 1 |
|5 | 2 | 2 |
trial
|id|accusedId|articleid|
------------------------
|1 | 1 | 1 |
|2 | 1 | 2 |
|3 | 2 | 1 |
|4 | 2 | 2 |
I want to get those accusedIds where all the articleIds of the first and the second tables are equal.
The above example should only return the accusedId 2, cause for accusedId 1 there is no articleId 3 in the second table.
I hope you understand what i mean. I'm currently writing my thesis in law, and the the time i was into sql is long gone by. Of course i already did some research, and tried several joins, but i was not able to find a solution. Hopefully you can help me.
Try something like this:
select a.accusedId , sum(a.accusedid) as cnt_a, sum(coalesce(b.accusedId, 0)) as cnt_b
from a left join b on a.accusedId = b.accusedId and a.articleId = b.articleId
group by accusedId
having cnt_a = cnt_b
I haven't even run that, so it might be a little off, but give it a lash. What it's doing is returning zeroes for a row in a not matched by b, so the HAVING clause will filter your grouped results to those where the article counts are equal.
Related
I'm new to SQL and i've been stuck with this problem.
I have 4 tables. I've filled them with some mock information.
Games Table
|ID |Name |Price |
|---|----------|------|
|1 |TestGame1 |2500 |
|2 |TestGame2 |1500 |
|3 |TestGame3 |3500 |
User Table
|ID |Username |Email |
|---|---------|--------------------|
|1 |TestUser1|testEmail1#email.com|
|2 |TestUser2|testEmail2#email.com|
|3 |TestUser3|testEmail3#email.com|
UserOwnsGame Table
|GameID |UserID |
|-------|-------|
|1 |1 |
|2 |2 |
|1 |2 |
|3 |1 |
|2 |1 |
Review Table
|GameID |UserID |Rating |Comment |LastEdit |
|-------|-------|-------|---------------------------------|----------|
|1 |1 |5.0 |I love this game |2022-04-19|
|1 |2 |4.5 |Came short of a 5.0 |2022-04-19|
|2 |2 |2.7 |Above average but nothing special|2022-04-19|
I want to scan through the data on all tables using a single query and get a table like the following,
GameID
UserID
Username
UserReviewCount
UserGameCount
Rating
Comment
LastEdit
1
1
TestUser1
2
3
5.0
I love this game
2022-04-19
1
2
TestUser1
1
2
4.5
Came short of a 5.0
2022-04-19
2
2
TestUser2
1
2
2.7
Above average but nothing special
2022-04-19
I want it for all reviews in the review table. I've tried multiple times. I can figure out ways to get the data on seperate queries. I can't figure out how to combine it all into one table like this. Especially considering the count().
Here;
UserReviewCount - Number of reviews user has made. Count on Review table.
UserGameCount - Number of games user owns. Count on UserOwnsGame table.
I've been stuck on this for one or two days now. Thank you for your help!
We can use a sub-query to count the number of games owned. We could have used another sub-query to count the number of reviews but, as we are already using the table, it is easier to use the window function count() over.
create table Games(ID int,Name varchar(10),Price int);
insert into Games values(1,'TestGame1',2500 ),(2,'TestGame2',1500 ),(3,'TestGame3',3500 );
create table Users (ID int, Username varchar(10),Email varchar(25));
insert into Users values(1,'TestUser1','testEmail1#email.com'),(2,'TestUser2','testEmail2#email.com'),(3,'TestUser3','testEmail3#email.com');
create table UserOwnsGame (GameID int, UserID int);
insert into UserOwnsGame values(1,1),(2,2),(1,2),(3,1),(2,1);
create table Review (GameID int,UserID int,Rating decimal(3,2),Comment varchar(50),LastEdit date);
insert into Review values(1,1,5.0,'I love this game','2022-04-19'),(1,2,4.5,'Came short of a 5.0','2022-04-19'),(2,2,2.7,'Above average but nothing special','2022-04-19');
select
r.GameID,
u.ID,
u.Username,
count(r.GameID) over (partition by r.UserID)
as UserReviewCount,
uog.number_games UserGamescount,
r.Rating,
r.Comment,
r.LastEdit
from
Users u
join Review r
on u.ID = r.UserID
join (select UserID,count(GameID) number_games
from UserOwnsGame
group by UserID) uog
on u.ID = uog.UserID;
GameID | ID | Username | UserReviewCount | UserGamescount | Rating | Comment | LastEdit
-----: | -: | :-------- | --------------: | -------------: | -----: | :-------------------------------- | :---------
1 | 1 | TestUser1 | 1 | 3 | 5.00 | I love this game | 2022-04-19
1 | 2 | TestUser2 | 2 | 2 | 4.50 | Came short of a 5.0 | 2022-04-19
2 | 2 | TestUser2 | 2 | 2 | 2.70 | Above average but nothing special | 2022-04-19
db<>fiddle here
I'm curious if there is an easy way to archive this query:
SomeTable.where(value_b: SomeTable.where(value_a: 1).pluck(:value_b))
For an example, if we have:
SomeTable
|id | a | b |
|1 | 1 | 2 |
|2 | 2 | 2 |
|3 | 3 | 3 |
|4 | 4 | 4 |
And the user enter number 1 into the system, I want to be able to find value of b where value of a = 1, which is 2. Then use this value of b to find all the records with this value.
So, I want to be able to use 1 and extract SomeTable with id: 1 and 2
Thanks!
SomeTable.joins("JOIN some_table as replica on replica.value_b = some_table.value_b")
.where(replica: {value_a: 1})
SomeTable.where("b in (SELECT b FROM some_tables where a = ?)", a_value)
a_value is your 'a' value to find 'b' value
I cannot seem to figure out a way to sort sql queries by joined children.
Database Example:
Table: posts
+------+---------+
| id | title |
+------+---------+
| 0 |'title1' |
| 1 |'title2' |
| 2 |'title3' |
+------+---------+
Table: post_meta
+------+---------+----------+---------+
| id | post_id | key | value |
+------+---------+----------+---------+
| 0 |0 |'coolness'| 5 |
| 1 |0 |'desc' |'random' |
| 2 |0 |'author' |'bill' |
| 3 |1 |'coolness'| 2 |
| 4 |1 |'desc ' |'random' |
| 5 |2 |'author' |'joe' |
| 6 |2 |'coolness'| 9 |
+------+---------+----------+---------+
I want a list of posts (or just post ids) ordered by their 'coolness' meta number (asc or desc). I dont know if I should be selecting from the posts table and joining on the meta table, or vise-versa. When I join on the post_meta table I only get data from one of the meta rows, so if I just add an order by post_meta.coolness nothing happens.
Thanks!
If you just want the id, you can use the post_meta table:
select pm.post_id
from post_meta pm
where pm.key = 'coolness'
order by pm.value + 0;
The + 0 is to convert the value (presumably a string) to a number.
If you need other columns related to the post, you can join in the posts table.
I have a rather simple (I think) question at hand. The example tables and the result I need are provided below (in reality those tables containt much more columns and data, I jest left what is relevant). There is also the query which returns exactly what I need. However, I dont like rather crude way in which it works (I dont like subqueries in general). The question is, how can I rewrite the query so it will automatically react to more columns appearing in TABLE2 in the future? Right now if the "z" column would be added to TABLE2, I need to modify each query in the code and add one more relevant subquery. I just want the select to read the entire content of TABLE2 and translate the id numbers to corresponding strings from TABLE1.
TABLE1
-----------------
id |x |
-----------------
567 |AAA |
345 |BBB |
341 |CCC |
827 |DDD |
632 |EEE |
503 |FFF |
945 |GGG |
234 |HHH |
764 |III |
123 |JJJ |
-----------------
TABLE2
-------------------------
id |x |y |
-------------------------
1 |123 |341 |
2 |567 |632 |
3 |345 |945 |
4 |764 |503 |
5 |234 |827 |
-------------------------
THE RESULT I NEED
-----------------
A |B |
-----------------
JJJ |CCC |
AAA |EEE |
BBB |GGG |
III |FFF |
HHH |DDD |
-----------------
The query I have
SELECT
(SELECT `x` FROM `TABLE1` WHERE `TABLE2`.`x` LIKE `TABLE1`.`id` LIMIT 1) as A,
(SELECT `x` FROM `TABLE1` WHERE `TABLE2`.`y` LIKE `TABLE1`.`id` LIMIT 1) as B
FROM `TABLE2` ORDER BY `id` DESC;
You might want to restructure your data model:
Instead of:
-------------------------
id |x |y |
-------------------------
1 |123 |341 |
2 |567 |632 |
3 |345 |945 |
4 |764 |503 |
5 |234 |827 |
-------------------------
You would have:
----------------------
col_id |col |
----------------------
1 |x |
2 |y |
----------------------
---------------------------
id |col_id |col_val |
---------------------------
1 |1 |123 |
1 |2 |341 |
2 |1 |567 |
2 |2 |632 |
etc
---------------------------
Probably not worth the hassle (you would effectively need to pivot when you're accessing multiple columns at a time) but it would allow you to do the query that you want across all current and future columns.
You can't do that with a plain select.
What you can do is creating a view with the translated values. You still have to modify the view when the original table is changed but your queries don't have to.
You can use dynamic sql statements, but still you can use the dynamic statements only if you are sure that table 2 will have the columns of same type like x and y(Apart from id).
Let me know if you are not sure how to write it.
All the best.
I currently have a table of concentrations, which are linked to a table of elements. There is a concentration table
|conc_id|element_id|conc|
and and element table
|element_id|symbol|
The concentration table only has element_ids for each conc_id that have non-zero concentrations.
What I am trying to do is create a query which will, for each concentration_id, list all the elements in order, with their concentration, regardless of whether they're non-zero or not. I have tried this in a number of increasingly complicated ways (starting with a RIGHT JOIN) but this always outputs a NULL conc_id when there is none of that element in it. The output I am looking for is something like this:
|conc_id|element_id|symbol|conc|
|1 |1 |H |1.2 |
|1 |2 |He |NULL|
|1 |3 |Li |2.3 |
...
|3 |1 |H |4.5 |
|3 |2 |He |NULL|
|3 |3 |Li |NULL|
...
And so on. Is there a way I can do this without having NULL conc_id?
Thanks for any help in advance...
First, you have to build a table that contains all combinations between conc_id and element_id:
SELECT DISTINCT conc_id, elements.element_id FROM concentrations, elements;
Which gives you the following table:
| conc_id | element_id |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
...
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
...
Once you have such a table, joining it with concentrations and elements should be fairly simple. For example:
SELECT combinations.conc_id, combinations.element_id, symbol, conc
FROM
(SELECT DISTINCT conc_id, elements.element_id FROM concentrations, elements) AS combinations
LEFT JOIN concentrations ON (combinations.conc_id = concentrations.conc_id AND combinations.element_id = concentrations.element_id)
LEFT JOIN elements ON (combinations.element_id = elements.element_id);
Result:
| conc_id | element_id | symbol | conc |
| 1 | 1 | H | 1.2 |
| 1 | 2 | He | NULL |
| 1 | 3 | Li | 2.3 |
...
| 3 | 1 | H | 4.5 |
| 3 | 2 | He | NULL |
| 3 | 3 | Li | NULL |
...
To be honest, I think the best way would be to actually fill in the missing data with zero values in the conc column. Otherwise, you're trying to hack it to display data that you don't actually have and it would be much more tangible than keeping null values anyway...
Assuming there are no performance consideration that this would impede, of course.
Assuming you do not have a simple list of all the conc_id somewhere, you could try something like:
SELECT c.conc_id, e.element_id, e.symbol, c2.conc
FROM
(SELECT DISTINCT conc_id FROM concentration c) c
INNER JOIN element e
LEFT JOIN concentration c2 ON c2.conc_id = c.conc_id AND c2.element_id = e.element_id
ORDER BY c.conc_id, e.element_id
The logic is:
Get a list of all unique conc_id derived table c
Do a cross join against element (for each row of c, list all row of element)
Left join against the full concentration table.
If you have another table with all the conc_id, you could avoid the derived table entirely.
select conc_id, conc.element_id, symbol, concentration from concentration_table as conc
join element_table as elem on conc.element_id = elem.element_id
order by conc.conc_id asc
This gives me this table:
conc_id element_id concentration element_id symbol
1 1 1.2 1 H
1 2 0 2 He
1 3 2.3 3 Li
3 1 4.5 1 H
3 2 0 2 He
3 3 0 3 Li
And these are the starting tables:
element_table:
element_id symbol
1 H
2 He
3 Li
concentration table:
conc_id element_id concentration
1 1 1.2
1 2 0
1 3 2.3
3 1 4.5
3 2 0
3 3 0
EDIT: edited the query to obtain correct table values requested