sql, sqlite SELECT with inner join - sql

I'm wondering how to select one column twice using an inner joinor some other way. my database is sqlite and i use PDO db driver.
My Example:
SELECT
orders.id,
orders.order_number,
clients.first_name,
clients.last_name,
users.name AS user_name
FROM orders
INNER JOIN clients ON
orders.client_id = clients.id
INNER JOIN users ON
orders.created_by = users.id
I want to get also, the user_name who edited this record
orders.edited_by = users.id
How to join this selection?

You'll need to use table aliases.
SELECT
orders.id,
orders.order_number,
clients.first_name,
clients.last_name,
creator.name AS creator_user_name
editor.name AS editor_user_name
FROM orders
INNER JOIN clients ON
orders.client_id = clients.id
INNER JOIN users creator ON
orders.created_by = creator.id
INNER JOIN users editor ON
orders.edited_by = editor.id

Use aliases in your table names, so you can use multiple references to the same table. This also can help make large queries easier to read.
SELECT
orders.id,
orders.order_number,
clients.first_name,
clients.last_name,
createUsers.name AS creator_name,
editUsers.name AS editor_name
FROM orders
INNER JOIN clients ON
orders.client_id = clients.id
INNER JOIN users As createUsers ON
orders.created_by = users.id
INNER JOIN users As editUsers ON
orders.edited_by = users.id
You can use as many "instances" of the same table as you wish.

Related

How to combine Inner Join and Left Join in SQL Query statement?

Given this Diagram:
What is the right way to use join that will includes all necessary fields from different tables (person name, employee number, status of contracts, job name, department name, pcn/item name, country, and religion)? BUT I want also to include all persons that choose not to put either thier country or religion. I have this query:
SELECT persons.fullname, religions.religion_name, countries.country_name
FROM countries INNER JOIN (religions INNER JOIN (persons INNER JOIN
((jobs INNER JOIN (departments INNER JOIN pcns ON departments.ID = pcns.department_id) ON jobs.ID = pcns.job_id)
INNER JOIN (employees INNER JOIN contracts ON employees.ID = contracts.employee_id) ON pcns.ID = contracts.pcn_id)
ON persons.ID = employees.person_id) ON religions.ID = persons.religion) ON countries.ID = persons.country_id;
I used LEFT JOIN but I got an error. Right now, I only query all my tables except for countries and religions then I made a function that whenever a user clicks particular person this function will return its religion and/or country. I am just curious how to achieve it in a SELECT query.

How to inner join with multiple tables for 3NF Normalization in SQL

I am trying to create normalization 3 nf (normal form) in this database. However, when I execute the query, the table is empty. As you will see, this is my table and diagram.
Here is the relationship that we want to 3NF
Torder->(Customer-Food-Carrier-Waiter)-(Ternary Relationship)-(Customer_id,Food_id,Carrier_id,Waiter_id)
Here is my query
SELECT
Customers.ID AS CustomerID,
Food.ID AS FoodID,
Carrier.ID AS CarrierID,
Waiter.ID AS WaiterID,
tOrder.ID AS TORDERID
FROM
tOrder
INNER JOIN
Customers ON Customers.ID = tOrder.Customer_id
INNER JOIN
Food ON Food.ID = tOrder.Food_id
INNER JOIN
Carrier ON Carrier.ID = tOrder.Carrier_id
INNER JOIN
Waiter ON Waiter.ID = tOrder.Waiter_id
ORDER BY tOrder.ID;
Clearly, you have an issue where some of the tables are empty or the ids do not match. You can use LEFT JOIN to keep all orders and see what is happening:
FROM tOrder o LEFT JOIN
Customers c
ON c.ID = o.Customer_id LEFT JOIN
Food f
ON f.ID = o.Food_id LEFT JOIN
Carrier ca
ON ca.ID = o.Carrier_id LEFT JOIN
Waiter w
ON w.ID = o.Waiter_id
If there are no matches, then the orders are still in the results, with NULL for the values in the table with no matches.
Note that this also introduces table aliases, so the query is easier to write and to read.

UPDATE with INNER JOIN on SQL Server

I have 2 tables Users and Orders. Primary key of Users is UserId, which I have defined as foreign key in the Orders table. I have added a new column of UserName to Orders. I want to import UserName from Users table.
I'm trying to run this code, but it keeps giving me errors. Can someone tell me what could be wrong?
UPDATE Orders
SET Orders.UserName = Users.UserName
INNER JOIN Users ON Orders.UserId = Users.UserId;
That's not the right syntax
UPDATE O
SET O.UserName = U.UserName
from Orders O
INNER JOIN Users U ON O.UserId = U.UserId ;
You need to start using Alias for tables references when there is more than one table involved in your query. Using Alias names makes the query more readable.
you are missing orders table name
UPDATE Orders
SET Orders.UserName = Users.UserName
from Orders
INNER JOIN Users ON Orders.UserId = Users.UserId ;
No UPDATE with INNER JOIN, please re-write your query as follow:
You can use INNER JOIN only after FROM clause
UPDATE Orders SET Orders.UserName = Users.UserName
FROM Users WHERE Orders.UserId = Users.UserId
I actually like the CTE version of the update here, because it lets us expression the join logic as we would in a select, without any potential confusion:
WITH cte AS (
SELECT o.UserName AS user_old, u.UserName AS user_new
FROM Orders o
INNER JOIN Users u ON u.UserId = o.UserId
)
UPDATE cte
SET user_old = user_new;
Your query structure should be like below :
UPDATE
t1
SET
t1.c1 = t2.c2,
t2.c2 = expression,
...
FROM
t1
[INNER | LEFT] JOIN t2 ON join_predicate
WHERE
where_predicate;
So your actual query should be like below :
UPDATE Orders SET Orders.UserName = Users.UserName
FROM Users WHERE Orders.UserId = Users.UserId

Two Inner Joins MYSQL

How would I preform two inner joins in one query?
Ie: three tables
Invoice
Address
Client
Invoice has a column which references an id in clients. It also has a column which references an address. I need to get both the clients name from the matched table and the address from the matched table. How would I INNER JOIN both tables?
I'll add a few details...
invoice has rows address(references address id), client(references client id), id and notes
client has rows first_name, last_name
address has rows street_name and city
I need to pull up
You can have as many JOIN clauses as you need in the query. Each has an ON clause where you specify the related columns between the joined tables.
SELECT
columns
FROM
invoice
INNER JOIN
address
ON
join_condition
INNER JOIN
client
ON
join_condition
Something like:
SELECT
c.*, i.*, a.*
FROM
invoices i
INNER JOIN
client c
ON
i.clientid = c.clientid
INNER JOIN
address a
ON
a.clientid = c.clientid
WHERE
i.id = 21
Don't forget you only select the fields you require, not * (all).
A sample e.g. based on learning from #Dan Grossman above:
SELECT FILM.TITLE, ACTOR.FIRST_NAME, ACTOR.LAST_NAME FROM ACTOR
INNER JOIN FILM_ACTOR
ON ACTOR.ACTOR_ID = FILM_ACTOR.ACTOR_ID
INNER JOIN FILM
ON FILM_ACTOR.FILM_ID = FILM.FILM_ID
WHERE ACTOR.FIRST_NAME = 'Nick' AND ACTOR.LAST_NAME = 'Wahlberg'

Why does this query return nothing?

This query works fine but I'm having trouble trying to figure out why it does not return anything if the user does not have any categories in the table "user_categories"? This is the table structure:
users: user id, username, user city
categories: category id, category name
user_categories: user id, category id
SELECT users.*, GROUP_CONCAT(categories.category_name) AS categories
FROM users
INNER JOIN user_categories ON users.user_id = user_categories.user_id
INNER JOIN categories ON user_categories.category_id = categories.category_id
WHERE users.user_city = 'brooklyn'
GROUP BY users.user_id
LIMIT 10
I just need for the new column "categories" to be empty if no rows existed for the user_id in user_categories...
Thanks!
You are using the wrong type of join - inner join will only succeed if a match is found in both tables. Instead, you want to try an outer join. Try something like this:
SELECT users.*, GROUP_CONCAT(categories.category_name) AS categories
FROM users
LEFT OUTER JOIN user_categories ON users.user_id = user_categories.user_id
LEFT OUTER JOIN categories ON user_categories.category_id = categories.category_id
WHERE users.user_city = 'brooklyn'
GROUP BY users.user_id
LIMIT 10
The Wikipedia SQL JOIN article is a pretty decent summary of the join types available.
SELECT users.*, GROUP_CONCAT(categories.category_name) AS categories
FROM users
LEFT JOIN
user_categories ON users.user_id = user_categories.user_id
LEFT JOIN
categories ON user_categories.category_id = categories.category_id
WHERE users.user_city = 'brooklyn'
GROUP BY
users.user_id
LIMIT 10
Note that on a MyISAM table, a subquery solution will probably be more efficient:
SELECT users.*,
(
SELECT GROUP_CONCAT(category_name)
FROM user_categories uc
JOIN categories c
ON c.category_id = uc.category_id
WHERE uc.user_id = users.id
) AS categories
FROM users
WHERE users.user_city = 'brooklyn'
ORDER BY
user_id
LIMIT 10
See this article in my blog for more detail:
Aggregates: subqueries vs. GROUP BY
An inner join will not return a record if there is not a record in both tables. You may be wanting a left outer join.
That's because you use an INNER JOIN to user_categories. If you use a LEFT JOIN, null data will be returned for that table if there is no corresponding ID for the user.