sql join joining 3 tables - sql

bit of a strange one this one...
Someone wrote a sql that in my mind shouldn't work, but it does and it also returns the correct results. I've written a simplified example, but I think it shows the point.
drop table #client;
drop table #transactions;
drop table #history;
create table #client (
clientId int,
name varchar(50)
);
create table #transactions (
transid int,
clientId int,
Amount int
);
create table #history (
transid int,
Amount int
);
insert into #client values (1, 'User 1');
insert into #client values (2, 'User 2');
insert into #client values (3, 'User 3');
insert into #transactions values (1, 1, 50);
insert into #transactions values (2, 1, 35);
insert into #transactions values (3, 1, 25);
insert into #transactions values (4, 2, 10);
insert into #transactions values (5, 2, 50);
insert into #transactions values (6, 1, 35);
insert into #transactions values (7, 3, 25);
insert into #transactions values (8, 3, 10);
insert into #history values (1, 50);
insert into #history values (2, 35);
insert into #history values (3, 25);
insert into #history values (4, 10);
insert into #history values (5, 50);
insert into #history values (6, 35);
insert into #history values (7, 25);
insert into #history values (8, 10);
select * from #history
join #transactions on #history.transid = #transactions.transid
join #client on #transactions.clientId = #client.clientId and #history.transid = #transactions.transid
The last join joins 3 tables together in one join, which shouldn't work from what I know of writing SQL. Am I wrong (which may very well be the case)

Why would you think it shouldn't work?
The last bit of the query is pointless though, and you can take it out. It's a simple join on 3 tables:
select * from #history
join #transactions on #history.transid = #transactions.transid
join #client on #transactions.clientId = #client.clientId

Related

SQL exclude negative quantity

Please help, there is a request in which sometimes there is a negative value in the KOLVO_RZ column. Is it possible to check this in the request and if the value is negative, then return 0?
SELECT KOLVO_T - KOLVO_KKM - KOLVO_RZ AS KOLVO_T
FROM PRICE
This should do the trick:
SELECT KOLVO_T - KOLVO_KKM - (CASE WHEN KOLVO_RZ < 0 THEN 0 ELSE KOLVO_RZ END) AS KOLVO_T
FROM PRICE
Here's a sample that works for me with InterBase 2020. Which InterBase version are you using?
create table hikers (
hiker_id integer not null,
name varchar (256) not null,
constraint pk_hid primary key (hiker_id));
create table hiker_data (
hiker_id integer not null,
steps_gained integer,
constraint fk_hid foreign key (hiker_id) references hikers (hiker_id));
commit;
insert into hikers values (1, 'Aarti');
insert into hikers values (2, 'Bala');
insert into hikers values (3, 'Chaaya');
insert into hikers values (4, 'Deepak');
insert into hiker_data values (1, 20);
insert into hiker_data values (1, 10);
insert into hiker_data values (1, -5);
insert into hiker_data values (1, 15);
insert into hiker_data values (1, -20);
insert into hiker_data values (2, 12);
insert into hiker_data values (2, 6);
insert into hiker_data values (2, 20);
insert into hiker_data values (2, -5);
insert into hiker_data values (2, 10);
insert into hiker_data values (2, -18);
insert into hiker_data values (3, 20);
insert into hiker_data values (3, 10);
insert into hiker_data values (3, -5);
insert into hiker_data values (3, 15);
insert into hiker_data values (3, -20);
insert into hiker_data values (3, 12);
insert into hiker_data values (4, 6);
insert into hiker_data values (4, 20);
insert into hiker_data values (4, -5);
insert into hiker_data values (4, 10);
insert into hiker_data values (4, -18);
commit;
/* test foreign key enforcement */
insert into hiker_data values (-100, -18);
and then, I execute the following queries successfully.
select hiker_id,
SUM(0 + (CASE WHEN steps_gained < 0 THEN 0
ELSE steps_gained
END)) AS total_steps_climbed,
SUM(0 + (CASE WHEN steps_gained > 0 THEN 0
ELSE steps_gained
END)) AS total_steps_descended,
SUM(steps_gained) AS final_tally
from hiker_data
group by hiker_id;
select hiker_id,
(CASE WHEN steps_gained < 0 THEN 0
ELSE steps_gained
END) AS steps_climbed
from hiker_data
where hiker_id=2;

SQL Server: Find the group of records existing in another group of records

I'm new to SQL Server and I searched for a solution to find, if a group is included in another group.
The query result should be grp_id 2 because 'A'+'B' is included in grp 3 and 5.
The result should be the grp_id of the the groups, that are included in other groups. With this result i´ll make an update of another table, joined with the grp_id.
The result should be:
+----+
| id |
+----+
| 2 |
+----+
I stuck in SQL because I do not find a solution to compare the groups. The idea was using bitwise comparison. But for that I had to add the value of each item in a field. I think there could be an easier way.
Thank you and best regards!
Eric
create table tmp_grpid (grp_id int);
create table tmp_grp (grp_id int, item_val nvarchar(10));
insert into tmp_grpid(grp_id) values (1);
insert into tmp_grpid(grp_id) values (2);
insert into tmp_grpid(grp_id) values (3);
insert into tmp_grpid(grp_id) values (4);
insert into tmp_grpid(grp_id) values (5);
--
insert into tmp_grp(grp_id, item_val) values (1, 'A');
insert into tmp_grp(grp_id, item_val) values (2, 'A');
insert into tmp_grp(grp_id, item_val) values (2, 'B');
insert into tmp_grp(grp_id, item_val) values (3, 'A');
insert into tmp_grp(grp_id, item_val) values (3, 'B');
insert into tmp_grp(grp_id, item_val) values (3, 'C');
insert into tmp_grp(grp_id, item_val) values (4, 'A');
insert into tmp_grp(grp_id, item_val) values (4, 'C');
insert into tmp_grp(grp_id, item_val) values (4, 'D');
insert into tmp_grp(grp_id, item_val) values (5, 'A');
insert into tmp_grp(grp_id, item_val) values (5, 'B');
insert into tmp_grp(grp_id, item_val) values (5, 'E');
Geez!
Technically speaking, group one is found in all other groups right? So, first a cross join to itself would be best with the condition that the values are the same AND that the groups are different, but before we do that we need to know how many items belong to each group so that's why we have the first select as a group that includes the count of elements per group, then join that with the cross join...Hope this helps.
select distinct dist_grpid
from
(select grp_id, count(*) cc from tmp_grp group by grp_id) g
inner join
(
select dist.grp_id dist_grpid, tmp_grp.grp_id, count(*) cc
from
tmp_grp dist
cross join tmp_grp
where
dist.item_val = tmp_grp.item_val and
dist.grp_id != tmp_grp.grp_id
group by
dist.grp_id,
tmp_grp.grp_id
) cj on g.grp_id = cj.dist_grpid and g.cc = cj.cc

Sample observations per group without replacement in SQL

Using the provided table I would like to sample let's say 2 users per day so that users assigned to the two days are different. Of course the problem I have is more sophisticated, but this simple example gives the idea.
drop table if exists test;
create table test (
user_id int,
day_of_week int);
insert into test values (1, 1);
insert into test values (1, 2);
insert into test values (2, 1);
insert into test values (2, 2);
insert into test values (3, 1);
insert into test values (3, 2);
insert into test values (4, 1);
insert into test values (4, 2);
insert into test values (5, 1);
insert into test values (5, 2);
insert into test values (6, 1);
insert into test values (6, 2);
The expected results would look like this:
create table results (
user_id int,
day_of_week int);
insert into results values (1, 1);
insert into results values (2, 1);
insert into results values (3, 2);
insert into results values (6, 2);
You can use window functions. Here is an example . . . although the details do depend on your database (functions for random numbers vary by database):
select t.*
from (select t.*, row_number() over (partition by day_of_week order by random()) as seqnum
from test t
) t
where seqnum <= 2;

Unknown column in where clause?

My code:
drop table if exists HSstudents;
create table HSstudents
(
HSsID int,
vNAAM text,
aNAAM text,
LT int,
GM float
);
insert into HSstudents values (1, 'Thomas', 'Jansen', 18, 7.0);
insert into HSstudents values (2, 'Jesse', 'Bakker', 19, 6.5);
insert into HSstudents values (3, 'Tom', 'Smit', 20, 7.1);
insert into HSstudents values (4, 'Jelle', 'Visser', 17, 9.6);
insert into HSstudents values (5, 'Sem', 'Dekker', 17, 8.1);
insert into HSstudents values (6, 'Anna', 'Peters', 18, 6.8);
insert into HSstudents values (7, 'Michelle', 'Hendriks', 19, 8.2);
insert into HSstudents values (8, 'Senna', 'Mulder', 20, 5.9);
insert into HSstudents values (9, 'Sven', 'Linden', 21, 6.0);
insert into HSstudents values (10, 'Ilse', 'Jacobs', 21, 7.5);
insert into HSstudents values (11, 'Harm', 'Schouten', 19, 7.0);
insert into HSstudents values (12, 'Emma', 'Dijkstra', 18, 8.1);
drop table if exists students;
create table students
(
sID int,
vNAAM text,
aNAAM text,
LT int
);
insert into students values (1, 'Thomas', 'Jansen', 18);
insert into students values (2, 'Jesse', 'Bakker', 19);
insert into students values (3, 'Tom', 'Smit', 20);
insert into students values (4, 'Jelle', 'Visser', 17);
insert into students values (5, 'Sem', 'Dekker', 17);
insert into students values (6, 'Anna', 'Peters', 18);
insert into students values (7, 'Michelle', 'Hendriks', 19);
insert into students values (8, 'Senna', 'Mulder', 20);
insert into students values (9, 'Sven', 'Linden', 21);
insert into students values (10, 'Ilse', 'Jacobs', 21);
insert into students values (11, 'Harm', 'Schouten', 19);
insert into students values (12, 'Emma', 'Dijkstra', 18);
drop table if exists applications;
create table applications
(
sID int,
aPROV text,
sPROV text,
taal text
);
insert into applications values (1, 'Overijssel', 'Drenthe', 'HTML');
insert into applications values (2, 'Gelderland', 'Overijssel', 'CSS');
insert into applications values (3, 'Groningen', 'Flevoland', 'CSS');
insert into applications values (4, 'Overijssel', 'Zuid-Holland', 'SQL');
insert into applications values (5, 'Noord-Holland', 'Drenthe', 'C#');
insert into applications values (6, 'Flevoland', 'Groningen', 'C#');
insert into applications values (7, 'Limburg', 'Groningen', 'JAVA');
insert into applications values (8, 'Limburg', 'Limburg', 'JAVASCRIPT');
insert into applications values (9, 'Drenthe', 'Noord-Brabant', 'CSS');
insert into applications values (10, 'Drenthe', 'Zeeland', 'Python');
insert into applications values (11, 'Zuid-Holland', 'Friesland', 'C++');
insert into applications values (12, 'Zeeland', 'Friesland', 'JAVA');
select
S.sID, S.vNAAM, S.aNAAM, S.LT, aPROV, sPROV, taal
from
HSstudents HS, students S, applications A
where
HSstudents.HSsID = students.sID
This results in an error
Code: 1054. Unknown column 'HSstudents.HSsID' in 'where clause'
How? Shouldn't it just work?
WHERE clause should follow the remane on the FROM clause:
where HS.HSsID = S.sID

SQL Query count

HI there I have this table,
Recipe = (idR, recipeTitle, prepText, cuisineType, mealType)
Ingredient = (idI, ingrDesc)
RecipIngr = (idR*, idI*)
and I'm trying to query a list for ingrDesc with a count of how many recipies that ingrDesc is in. I want to list only those ingrDesc that occur more than 10 times.
Here's what I have:
SELECT a.idI, a.recipeTitle
FROM Recipe a
INNER JOIN recpingr b
ON a.idr = b.idr
WHERE a.preptext = '>10'
Any help as I don't know how to carry on with this query
Use GROUP BY with HAVING:
SELECT i.idI, i.ingrDesc, COUNT(*)
FROM Ingredient i
INNER JOIN RecipIngr ri ON i.idI = ri.idI
GROUP BY i.idI, i.ingrDesc
HAVING COUNT(*) > 10
You need to use a group by clause and having. I have created a quick sample here but my sample data does not go up to 10 so I used any ingredient that was used more than once (> 1).
Here is the sample data:
create table dbo.recipe (
idR int not null,
recipeTitle varchar(100) not null,
prepText varchar(4000) null,
cuisineType varchar(100) null,
mealType varchar(100) null
)
go
insert into dbo.recipe values (1, 'Eggs and Bacon', 'Prep Text 1', 'American', 'Breakfast')
insert into dbo.recipe values (2, 'Turkey Sandwich', 'Prep Text 2', 'American', 'Lunch')
insert into dbo.recipe values (3, 'Roast Beef Sandwich', 'Prep Text 3', 'American', 'Lunch')
go
create table dbo.ingredient (
idI int not null,
ingrDesc varchar(200) not null
)
go
insert into dbo.ingredient values (1, 'Large Egg')
insert into dbo.ingredient values (2, 'Bacon');
insert into dbo.ingredient values (3, 'Butter');
insert into dbo.ingredient values (4, 'Sliced Turkey');
insert into dbo.ingredient values (5, 'Lettuce');
insert into dbo.ingredient values (6, 'Tomato');
insert into dbo.ingredient values (7, 'Onion');
insert into dbo.ingredient values (8, 'Bread');
insert into dbo.ingredient values (9, 'Mustard');
insert into dbo.ingredient values (10, 'Horseradish');
insert into dbo.ingredient values (11, 'Sliced Roast Beef');
go
create table dbo.recipingr(
idR int not null,
idI int not null
)
go
insert into dbo.recipingr values (1, 1);
insert into dbo.recipingr values (1, 2);
insert into dbo.recipingr values (2, 4);
insert into dbo.recipingr values (2, 5);
insert into dbo.recipingr values (2, 6);
insert into dbo.recipingr values (2, 7);
insert into dbo.recipingr values (2, 8);
insert into dbo.recipingr values (2, 9);
insert into dbo.recipingr values (3, 11);
insert into dbo.recipingr values (3, 10);
insert into dbo.recipingr values (3, 8);
insert into dbo.recipingr values (3, 6);
insert into dbo.recipingr values (3, 5);
go
Here is the query:
select
i.ingrDesc,
count(*) ingrCount
from
dbo.recipe r
inner join dbo.recipingr ri on ri.idR = r.idR
inner join dbo.ingredient i on i.idI = ri.idI
group by
i.ingrDesc
having
count(*) > 1