How to perform Sql Join Query on more than two tables? - asp.net

I have a table named "tbl_category" which contains the following fields:
category_id int auto_increment primary key,
category_title varchar(max),
category_description varchar(max) //is the foreign key in "tbl_sub_category"
And another table is "tbl_sub_category" which have the following fields:
sub_category_id int auto_increment primary key,
sub_cateogry varchar(max),
cateogry_id int auto_increment
Now, I want to display sub_category with its corresponding category_title. Can any help me out?

Use this query
SELECT c.category_title, s.sub_category
FROM tbl_category c
INNER JOIN tbl_sub_category s ON c.category_id = s.category_id

SELECT sub_category,category_title FROM tbl_category,tbl_sub_category
WHERE tbl_category.category_id=tbl_sub_category.category_id;

This is with a minor modification on the previous query, The previous queries would work fine if corresponding to each category an entry is available in subcategory table. If it is not the case, use outer join.
SELECT c.category_title, s.sub_category
FROM tbl_category c
LEFT OUTER JOIN tbl_sub_category s
ON c.category_id = s.category_id
CategoryID in subcategory table cannot be auto-increment.

SELECT
s.sub_category_id,
s.sub_cateogry,
c.category_title
FROM
tbl_sub_category s
INNER JOIN
tbl_category c
ON s.cateogry_id = c.category_id
The above example will only ever display items that are in the tbl_sub_category that have a corresponding foreign key in tbl_category. The INNER JOIN is stating to only return rows that have the foreign key relationship, while the FROM starts with tbl_sub_category which ensures we're only looking at sub categories. You can easily reverse these two so that the FROM is on the tbl_category and the INNER JOIN is on the tbl_sub_category which would produce the same results, but in this example you're being more explicit that you're interested in the sub categories and not the categories.

Related

SQLite Order By foreign table field

I have two tables like following: (They have much more fields in reality)
Records (
recordId INTEGER PRIMARY KEY,
dateTime TEXT
);
Alarms (
alarmId INTEGER PRIMARY KEY,
recordId INTEGER,
FOREIGN KEY (recordId) REFERENCES Records(recordId)
ON UPDATE CASCADE
ON DELETE CASCADE
);
I want to get all Alarms sorted by dateTime of Record they are referring. I think it should be something like this:
SELECT * FROM Alarms ORDER BY Records.dateTime DESC;
But I couldn't find any relatable example.
Thank you for your time.
What you need is a join of the 2 tables:
SELECT a.*
FROM Alarms a INNER JOIN Records r
ON r.recordId = a.recordId
ORDER BY r.dateTime DESC;
Or a correlated subquery in the ORDER BY clause:
SELECT a.*
FROM Alarms a
ORDER BY (SELECT r.dateTime FROM Records r WHERE r.recordId = a.recordId) DESC;

SQLite search two tables

In a SQLite database, I have created two tables:
CREATE Table Master (ItemID VARCHAR PRIMARY KEY, Property VARCHAR)
CREATE Table Counter (OtherID VARCHAR PRIMARY KEY, ItemID VARCHAR)
Records on table Master:
* ItemID: Book, Property: large
* ItemID: Table, Property: green
Records on table Counter:
* OtherID: random1, ItemID: Book
* OtherID: random2, ItemID: Book
* OtherID: random3, ItemID: Book
The column ItemID on table Master has the same contents as the same-named column on table Counter.
What is the correct SQL select statement to get all rows from table Master sorted by the number of their records in table Counter ?
In this case, row "Book" has three counts in table Counter and should be listed on first position, while row "Table" has no counts and should be the second result.
I know how to do this on one table but never managed to get a SQL select statement working that spans two tables.
Any help is appreciated.
By the way: I cannot change the table structure; so not sure if there would be something better, but I have to work with the tables as they are.
attach to two different databases
access tables with "db?." in front
join both tables on the common semantic, i.e. the ItemId
left join to get the "empty" lines, too, with "0" count
make groups which represent the lines you want in the output, i.e. also by ItemId
grouping allows using the aggregate function "count()"
order according to desired output, i.e. by count, but descending to get "3" first
select the ItemId and the property to match desired output
Code:
attach 'master.db' as dbm;
attach 'counter.db' as dbc;
select a.ItemId, property
from dbm.Master a LEFT JOIN dbc.Counter b
using (ItemId)
group by a.ItemId
order by count(OtherId) desc;
Tested with :
echo .dump | sqlite3 counter.db
BEGIN TRANSACTION;
CREATE TABLE Counter (OtherID VARCHAR PRIMARY KEY, ItemID VARCHAR);
INSERT INTO Counter VALUES('random1','book');
INSERT INTO Counter VALUES('random2','book');
INSERT INTO Counter VALUES('random3','book');
COMMIT;
echo .dump | sqlite3 master.db
BEGIN TRANSACTION;
CREATE TABLE Master (ItemID VARCHAR PRIMARY KEY, Property VARCHAR);
INSERT INTO Master VALUES('book','large');
INSERT INTO Master VALUES('table','green');
COMMIT;
Output:
book|large
table|green
If I understand you, I think this should work:
SELECT M.ItemId, Property
FROM Master M
LEFT JOIN Counter C
ON M.itemid=C.itemid
GROUP BY C.itemid
ORDER BY COUNT(C.itemid) DESC;

How to use a nested inner join statement?

I have created three tables such that:
CREATE TABLE guest(
name varchar(100),
ranking int,
PRIMARY KEY (name)
);
CREATE TABLE room(
roomname varchar(100),
wallcolor varchar(100),
rating int,
PRIMARY KEY(roomnane)
);
CREATE TABLE reservation(
name varchar(100),
roomname varchar(100),
day varchar(100),
moveinday int,
moveoutday int,
PRIMARY KEY(roomname, day, start, finish),
FOREIGN KEY(roomname) REFERENCES room(roomname),
FOREIGN KEY(name) REFERENCES guest(name)
);
I am trying to write a DELETE query to delete all the guests that are not qualified to rent any room. Qualified to rent means the guests ranking is greater than or equal to room ranking. Pretty much delete the reservation entry, and the guest too if they don't qualify
I tried
DELETE
FROM
reservation, guest
INNER JOIN (
SELECT
reservation.roomname,
reservation.day,
reservation.start,
reservation.finish
FROM
guest
INNER JOIN reservation ON reservation.name = guest.name
INNER JOIN room ON reservation.roomname = room.roomname
WHERE
room.rating > guest.ranking
) invalidReservationTable
ON reservation.roomname = invalidReservationTable.roomname
AND reservation.day = invalidReservationTable.day
AND reservation.start = invalidReservationTable.start
AND reservation.finish = invalidReservationTable.finish;
I am getting an error when I run this on sqlite on the Inner Join statement following the FROM reservation line. What am I doing wrong? Am I on the right track to delete just the reservation?
You cannot delete from multiple tables in same statement. Consider separating into two action queries: first on reservations table due to foreign key constraints, then on guests table, adding a WHERE clause subquery that conditions to your needs.
First, reservations delete:
DELETE FROM reservation
WHERE name IN
(SELECT reservation.name
FROM guest
INNER JOIN reservation ON reservation.name = guest.name
INNER JOIN room ON reservation.roomname = room.roomname
WHERE room.rating > guest.ranking);
Then guests table delete. However, the guest's corresponding reservation would no longer exist per query before. Hence, you should now remove guests without any reservations which you can handle with LEFT JOIN...NULL.
DELETE FROM guest
WHERE name IN
(SELECT guest.name
FROM guest
LEFT JOIN reservation ON reservation.name = guest.name
WHERE reservation.name IS NULL)
By the way, reconsider design here. In one-to-many relationships, the many-to-many table should be the only delete interaction. Guests (who may make future reservations) should not be regularly cleaned out. And have your app/script validate ranking/rating prior to making reservation.

How to use left outer join in my sql query?

Here is my query:
ALTER PROCEDURE sp_logdetails
(
#bookid INT
)
AS
BEGIN
SELECT *
FROM book_lending
LEFT OUTER JOIN student ON student.id = book_lending.id
WHERE bookid = #bookid
END
When i execute above query, it shows only book_lending data, not the student data. Here is my screenshot
And it is my student table data screenshot:
May i know, how to get student data in which particular bookid. I used to set foreign key for book_lending id to student id.
Can anyone guide me to fix this?
Thanks,
Select the specific columns from joined table in your select list. Here bl and s is table alias for better redability. You need to select the columns you want and include them to your select list. below query will select all columns from both tables.
SELECT bl.*, s.*
FROM book_lending bl
LEFT OUTER JOIN student s ON s.id = bl.id
AND bl.bookid = #bookid
You got the fields mixed up in the join:
LEFT OUTER JOIN student ON student.id = book_lending.id
You try to match a student to book lending by ID of both - which is wrong.
Change the code to this and you will start getting results back:
SELECT *
FROM book_lending
LEFT OUTER JOIN student ON student.id = book_lending.studentid
WHERE bookid = #bookid

SQLite outer join column filtering

As a training exercise I'm working on a fictional SQLite database resembling League of Legends, and I need to perform a left outer join to get a table of all players and if they have skins that are not called 'Classic', return those too.
I currently have this query:
SELECT * FROM players
LEFT OUTER JOIN (SELECT * FROM playerchampions WHERE NOT championskin = 'Classic')
ON name = playername
Which returns what I am looking for, but also a lot of columns I don't want (player experience, player IP, player RP, playername in the playerchampions table. The code for the two tables is as following:
CREATE TABLE players (
name TEXT PRIMARY KEY,
experience INTEGER,
currencyip INTEGER,
currencyrp INTEGER
);
CREATE TABLE playerchampions (
playername TEXT REFERENCES players ( name ) ON UPDATE CASCADE,
championname TEXT REFERENCES champions ( name ) ON UPDATE CASCADE,
championskin TEXT REFERENCES skins ( skinname ) ON UPDATE CASCADE,
PRIMARY KEY ( playername, championname, championskin )
);
As I said, the query executes, but I can't use SELECT players.name, playerchampions.championname, playerchampions.championskin as the playerchampions columns are not given their proper table name when returned.
How do I fix this?
Try using aliases:
SELECT p.name, c.championskin FROM players p LEFT OUTER JOIN (SELECT pc.playername playername, pc.championskin championskin FROM playerchampions pc WHERE NOT pc.championskin = 'Classic') c ON p.name = c.playername;
Not sure if its exactly what you need, but it will get you closer...
SELECT * FROM players p LEFT OUTER JOIN playerchampions pc ON (p.name = pc.playername) WHERE NOT pc.championskin = 'Classic'

Resources