I am trying to retrieve every data stored in 2 tabs from my database through a SELECT statement.
The problem is there are a lot of columns in each tab and manually selecting each column would be a pain in the ass.
So naturally I thought about using a join :
select * from equipment
join data
on equipment.id = data.equipmentId
The problem is I am getting the equipment ID 2 times in the result.
I thought that maybe some specific join could help me filter out the duplicate key, but I can't manage to find a way...
Is there any way to filter out the foreign key or is there a better way to do the whole thing (I would rather not have to post process the data to manually remove those duplicate columns)?
You can use USING clause.
"The USING clause specifies which columns to test for equality when
two tables are joined. It can be used instead of an ON clause in the
JOIN operations that have an explicit join clause."
select *
from test
join test2 using(id)
Here is a demo
You can also use NATURAL JOIN
select *
from test
natural join test2;
I seem to be missing something. I keep reading that you should use a join instead of a sub-select in most articles I read. However running a quick experiment myself shows a big win for the sub-query when it comes down to execution time.
Trying to get all first names of people that have made a bid (I presume the tables speak for themselves) results in the follwing.
This join takes 10 seconds
select U.firstname
from Bid B
inner join [User] U on U.userName = B.[user]
This query with sub-query takes 3 seconds
select firstname
from [User]
where userName in (select [user] from bid)
Why is my experiment not in line with what I keep reading everywhere or am I missing something?
Experimenting on I found that execution times are the same after adding distinct to both.
They're not the same thing. In the query with joins you can potentially multiply rows or have rows entirely removed from the results.
Inner Join removes rows on non-matched keys. It also multiplies rows on any matched keys that repeat in either one or both tables being joined. Inner Join therefor goes through the additional step of multiplying and removing rows.
The subquery you used is a SELECT. Since there are no filters using a WHERE it is as fast as a simple SELECT and since there are no joins you get results as fast as the results can be selected.
Some may argue that Outer joins return NULLs similar to sub-queries- but they can still multiply rows. Hence, sub-queries and joins are not the same thing.
In the queries you provided, you want to use the 2nd query (the one with the subquery) since it doesn't multiply or remove rows.
Good Read for Subquery vs Inner Join
https://www.essentialsql.com/subquery-versus-inner-join/
I've written a query to filter a table based on criteria found in a master table, and then remove rows that match a third table. I'm executing the query in Access, so I can't use MINUS. It works, but I found that it returns duplicate rows for some, but not all, of the selected records. I fixed it with DISTINCT, but I don't know why it would return duplicates in the first place. It's a pretty simple query:
select distinct sq.*
from
(select List_to_Check.*, Master_List.SELECTION_VAR
from List_to_Check
left join Master_List
on List_to_Check.SUB_ID = Master_List.SUB_ID
where Master_List.SELECTION_VAR = 'criteria'
) as sq
left join List_to_Exclude
on sq.SUB_ID = List_to_Exclude.SUB_ID
where List_to_Exclude.SUB_ID is null
;
Edit: The relationships between all three tables are 1-to-1 on the SUB_ID var. Combined with using a LEFT JOIN, I would expect one line per ID.
I recommend breaking your query apart and checking for duplicates. My guess is that it's your data/ the sub_ID isn't very unique.
Start with you sub query since you're returning all of those columns. If you get duplicates there, your query is going to return duplicates regardless of what is in your exclusion table.
Once you have those duplicates cleared up, check the exclusion table for duplicate sub_Id.
To save time in trouble-shooting, if there are known culprits that are duplicates, you may want to limit the returned values, so you can focus on the peculiarities of those data.
I'm not sure this is a problem, but look into the logic on
on List_to_Check.SUB_ID =
Master_List.SUB_ID
where Master_List.SELECTION_VAR = 'criteria'
Where clauses on data in the right side of a left outer join may not be returning the data you expect. Try this and see what happens:
on List_to_Check.SUB_ID = Master_List.SUB_ID
and Master_List.SELECTION_VAR = 'criteria'
The inner query joins List_to_Check and master but the outer query joins List_to_Exclude with Subscriber(maybe you can change the names i call these 3 tables)
To avoid duplicates you need to use one of the table in both the queries inner and outer. This will avoid duplicates.
I have two tables like this:
I want to select In and Out values from log details where id=1 in log table.
I tried this for In value:
SELECT Log.Time, LogDetail.Value
FROM Log where ID=1
INNER JOIN LogDetail
ON Log.ID=LogDetail.ID where Name="In";
Is this a true query?
If you will try to run this query - you will see it can't be executed. The reason is two where statements it contains.
Query can contain only one where statement in most DBMS (while this statement can contain multiple conditions joined together by logical operators).
Also it is better to use table aliases - this makes query more readable and prevents possible ambiguities.
So your query should look like:
select L.Time, LD.Value
from Log as L
inner join LogDetail as LD on L.ID=LD.ID
where L.ID=1 and LD.Name="In"
I'm trying to get 2 results into 1 html table, the results of a user being kicked/banned. A UUID is a unique code for every user.
The UUID is stored in BAT_players.
The player name is also stored in BAT_players
There are 3 table's: BAT_players, BAT_ban and BAT_kick
I'm trying to get the history of a user in a html table, this includes kicks and bans. Right now there are only bans in this history, i'm trying to add kicks too. This query is working fine, it shows only bans though.
SELECT BAT_ban.ban_staff, BAT_ban.ban_state, BAT_ban.ban_server, BAT_ban.ban_begin, BAT_ban.ban_end, BAT_ban.ban_id, BAT_kick.kick_id, BAT_ban.ban_reason, BAT_players.BAT_player, ban_soort
FROM BAT_players
INNER JOIN BAT_ban
ON BAT_ban.UUID=BAT_players.UUID
Unfortunately it is not working with this query, it's giving me an empty history. What am i doing wrong with the second inner join?
SELECT BAT_ban.ban_staff, BAT_ban.ban_state, BAT_ban.ban_server, BAT_ban.ban_begin, BAT_ban.ban_end, BAT_ban.ban_id, BAT_kick.kick_id, BAT_ban.ban_reason, BAT_players.BAT_player, ban_soort
FROM BAT_players
INNER JOIN BAT_ban
ON BAT_ban.UUID=BAT_players.UUID
INNER JOIN BAT_kick
ON BAT_kick.UUID=BAT_players.UUID ORDER BY ban_id DESC
;
Thanks!
The problem is that a "null" on any of your inner joins will eliminate that row from the result set.
One solution (perhaps the best solution) is to use left joins.
Another is to take the UNION of two inner joins.
Here's a great link to help visualize INNER, OUTER, LEFT and RIGHT joins:
http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
Try using LEFT JOIN:
SELECT BAT_ban.ban_staff, BAT_ban.ban_state, BAT_ban.ban_server, BAT_ban.ban_begin, BAT_ban.ban_end, BAT_ban.ban_id, BAT_kick.kick_id, BAT_ban.ban_reason, BAT_players.BAT_player, ban_soort
FROM BAT_players LEFT JOIN
BAT_ban ON BAT_ban.UUID=BAT_players.UUID LEFT JOIN
BAT_kick ON BAT_kick.UUID=BAT_players.UUID
ORDER BY ban_id DESC
To replace NULL values with empty strings (for SQL Server):
SELECT ISNULL(BAT_ban.ban_staff,''), ISNULL(BAT_ban.ban_state,''), ISNULL(BAT_ban.ban_server,''), ISNULL(BAT_ban.ban_begin,''), ISNULL(BAT_ban.ban_end,''), ISNULL(BAT_ban.ban_id,''), ISNULL(BAT_kick.kick_id,''), ISNULL(BAT_ban.ban_reason,''), BAT_players.BAT_player, ban_soort
FROM BAT_players LEFT JOIN
BAT_ban ON BAT_ban.UUID=BAT_players.UUID LEFT JOIN
BAT_kick ON BAT_kick.UUID=BAT_players.UUID
ORDER BY ban_id DESC
For MySQL, replace ISNULL with IFNULL.
An INNER JOIN requires a value in both tables, so if you use it for both kicks and bans, you will only see users who have been both kicked and banned.
To show users who have been either kicked or banned, you need to change both joins to LEFT JOIN, which essentially means "join if you can, but don't discard rows if you can't". That will include users who have been neither kicked nor banned, so you will also want an extra condition in the WHERE clause saying BAT_ban.ban_id IS NOT NULL OR BAT_kick.kick_id IS NOT NULL.
Note that where a user has multiple bans and multiple kicks, this will produce a row for every combination of ban and kick, since there is no rule to determine which ban should line up with which kick.
An alternative is to write two queries, each using INNER JOIN, and then combine the results. If you give them the same number and type of output columns (leaving NULL for those which aren't applicable) you can use UNION to run both and return the complete result set in one go.