SQL query to relate 2 tables - sqlite

I want to relate following 2 tables in sqlite3. What I understood from other examples is that we should have some common field between each table, so I added order_ID.
1) How to write sqlite queries for creating the relation between these tables?
2) How to manage Table 2, where same order can have multiple products, so order ID is repeated. An order can have min 1 and max 10 products. So it has dynamic range of 1-10.
table 1:
order_ID date buyer ship_chr
001 01/01 abc 15
002 05/01 xyz 10
table 2:
order_ID prod quantity rate
001 pen 50 2
001 paper 25 1
001 pin 50 2
002 paper 25 1
002 pen 100 2

It looks like you want to store orders and information about those orders. First, make an orders table.
create table orders (
id integer primary key autoincrement,
created_at timestamp not null default current_timestamp,
buyer text not null,
ship_chr text not null
)
Note that instead of order_id, the primary key of a table is just id.
It's not required, but it is a convention I like as it keeps primary and foreign keys distinct.
Also note that I'm using the timestamp type to store dates, this will make working with those dates much easier as you can use SQLite date functions.
Now we need a table for information about what is in each order.
create table order_products (
id integer primary key autoincrement,
order_id integer not null references orders(id),
product text not null,
quantity integer not null,
rate integer not null
)
This sets up a one-to-many relationship betweeen orders and order_products.
One order can have many products. You can link these tables together using
a join. Here's how you'd get
the buyer for each product.
select o.buyer, op.product, op.quantity
from order_products op
join orders o on o.id = op.order_id
abc|pen|50
abc|paper|25
abc|pin|50
xyz|paper|25
xyz|pen|100
join orders o on o.id = op.order_id says for every row in order_products find one in orders where order.id matches the row's order_id and treat them both as a single row.
From here you'll probably want to make products and buyer their own tables
as well to store any information about the buyers and products. It also ensures
that the products and buyers exist avoiding typos.
create table buyers (
id integer primary key autoincrement,
name text not null,
address text not null,
phone text not null
);
create table products (
id integer primary key autoincrement,
name text not null,
stock integer not null default 0
);
create table orders (
id integer primary key autoincrement,
created_at timestamp not null default current_timestamp,
buyer_id integer references buyers(id) not null,
ship_chr text not null
);
create table order_products (
id integer primary key autoincrement,
order_id integer not null references orders(id),
product_id integer not null references products(id),
quantity integer not null,
rate integer not null
);
Then you can join everything together to get information about products and buyers.
select b.name, p.name, op.quantity
from order_products op
join orders o on o.id = op.order_id
join buyers b on b.id = o.buyer_id
join products p on p.id = op.product_id
name|name|quantity
abc|pen|50
abc|paper|25
abc|pin|50
xyz|paper|25
xyz|pen|100
SQL Fiddle
If you don't do this now it will be harder to do later.

Related

get count of all related column on relationship

in sqlite i have this tables:
CREATE TABLE sessions(
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_name TEXT,
session_comment TEXT,
session_type INTEGER,
date_time TEXT)
CREATE TABLE barcodes(
id INTEGER PRIMARY KEY AUTOINCREMENT,
barcode TEXT,
session_id INTEGER,
enter INTEGER,
exit INTEGER,
date_time TEXT)
sessions is main table and i store some data in other table as barcodes with specifying session_id in barcodes table, now i want to get all column data from sessions with count of all barcodes table witch session_id in that equals with sessions.id
for example:
select *, count(barcodes) as cnt from sessions
left join barcodes on sessions.id = barcodes.session_id
try below query
SELECT *, COUNT(b.barcodes) as cnt FROM
sessions s
LEFT JOIN barcodes b ON s.id = b.session_id
GROUP BY b.id

Pull data from two separate SQL tables based on a JOIN but that uses a column not in the JOIN or the SELECT

This is based on a Khan Academy course. I have 2 SQLite tables:
CREATE TABLE table1 (id STRING PRIMARY KEY, charge_id TEXT, amount INTEGER, currency INTEGER, country STRING);
INSERT INTO table1
( id, charge_id, amount, currency, country) VALUES
('0xb01', '0x1', 2000, 'USD', 'USA'),
('0x0a1', '0x1', 500, 'USD', 'USA'),
('0x0c1', '0x1', 1000, 'CAD', 'USA'),
('0xs31', '0x4', 1000, 'YEN', 'CA');
CREATE TABLE table2 (id STRING PRIMARY KEY, charge_id TEXT, value VARIABLE);
INSERT INTO table2
( id, charge_id, value ) VALUES
('0x34s', '0x1', '123 main street'),
('0x3ze', '0x1', 'merchant-id-001'),
('0x3w2', '0x2', 'zip-code-90210' ),
('0x35k', '0x2', 'merchant-id-002');
I would SELECT the amount, currency and country from table 1 (Charges) and join with table 2 (Metadata) based on the id. Charges uses ID, while Metadata stores meta tags, with a unique identifier [id] equal to the charge [id] from Charges. I want to group the total amount, total currency for each merchant_id and only those charges that were made in the USA.
Step-by-step pseudo code:
(1) find all charges in the USA (Charges country)
(2) match all charge_ids from Charges (id) to charges in Metadata (id)
(3) separate each charge by the merchant_id (Metadata value)
(4) display the total amount, currency by merchant_id (amount, Charges currency, value)
This is a difficult because :
(1) I want to select from Charges and
(2) join to Metadata by the [id]
(3) but each Metadata record only has the charge_id and a metadata tag, which would match the merchant_id with the charge
The query result I would like is:
value (merchant id) currency total amount
merchant-id-001 usd 2500
merchant-id-001 cad 1000
merchant-id-002 yen 200
merchant-id-002 cad 50
Currently I have this query but it does not seem to be working:
select table1.amount, table1.currency, table1.country, count(*)
from table1
LEFT JOIN table1
UNION ALL
SELECT table2.value
FROM CHARGES_table2
LEFT JOIN table2
ON table1.id = table2.id
WHERE table1.country = 'USA'
GROUP BY table2.value
I am getting errors on union parameters: 2,1
Read the grammar & other documentation for the expressions you are using. The arguments to UNION are two SELECTs & it can have a final ORDER BY. Here's the parse:
select table1.amount, table1.currency, table1.country, count(*)
from table1
LEFT JOIN table1
UNION ALL
SELECT table2.value
FROM CHARGES_table2
LEFT JOIN table2
ON table1.id = table2.id
WHERE table1.country = 'USA'
GROUP BY table2.value
UNION is putting its arguments' rows into one table so it also requires that their columns agree in number & have compatible types. Here the numbers disagree.
There is no table1 in scope in the second SELECT so that is an error in isolation that is moot given the UNION.

Oracle: object relational database, how to insert table values with foreign key?

Actually, I have two tables Branch and Account_table and I want to insert the account_table values with a foreign key(bID) values which is primary key in Branch Table (bID) but I am getting errors while inserting values. Following is my code.
create type bank_branch as object(
bID varchar2(10),
street varchar2(20),
city varchar2(20),
zipcode varchar2(10),
bPhone varchar2(20))
not final
/
create table branch of bank_branch(
primary key (bID),
/
insert into branch values(
'601','XYZ Street','Orlando','OR112AB','024771169');
/
insert into branch values(
'620','Terrace Road','California','CL229JH','548711131');
/
insert into branch values(
'630','Miami Street','Miami','M21334A','9665411211');
/
create type account_type as object(
accNum int,
accType varchar2(15),
balance number,
bID varchar2(10),
interest number,
overdraftLimit number,
openDate DATE)
/
create table account_table of account_type(
primary key (accNum),
FOREIGN key (bID) REFERENCES branch(bID));
/
insert into account_table
select 'bID', b.BID
from branch b
where b.BID = 601,
'1001','current','630.87','0.009','400','10-Sep-14');
/
Thanks.
create type bank_branch as object(
bID varchar2(10),
street varchar2(20),
city varchar2(20),
zipcode varchar2(10),
bPhone varchar2(20))
not final
/
create table branch of bank_branch(
primary key (bID));
/
insert into branch values(
'601','XYZ Street','Orlando','OR112AB','024771169');
/
insert into branch values(
'620','Terrace Road','California','CL229JH','548711131');
/
insert into branch values(
'630','Miami Street','Miami','M21334A','9665411211');
/
create type account_type as object(
accNum int,
accType varchar2(15),
balance number,
bID varchar2(10),
interest number,
overdraftLimit number,
openDate DATE);
/
create table account_table of account_type(
primary key (accNum),
FOREIGN key (bID) REFERENCES branch(bID));
/
insert into account_table
select '1001','current','630.87',b.BID,'0.009','400','10-Sep-14'
from branch b
where b.BID = 601;
/
1 row(s) inserted.
I have used the same code as yours. Only the insert statement differs. It works fine for me.

SQLite: Loop over SELECT statement, replacing the WHERE clause

I have following two tables:
CREATE TABLE messages (
id integer UNIQUE NOT NULL,
message text,
recipient integer NOT NULL,
sender integer NOT NULL,
sent_at text NOT NULL,
FOREIGN KEY (recipient) REFERENCES users (id),
FOREIGN KEY (sender) REFERENCES users (id)
);
CREATE TABLE users (
id integer UNIQUE NOT NULL,
username text NOT NULL,
);
I need a very specific query, that looks like the following:
SELECT *
FROM messages
WHERE sender = 123 OR recipient = 123
ORDER BY id desc
LIMIT 1
I need to kind of iterate over the messages table, using every user, and putting him in the WHERE statement.
-- TABLE 'users':
-- 123 = id of user1
-- 456 = id of user2
-- 789 = id of user3
Is it possible to iterate in SQLite?
Goal is, to get the newest "conversation" for every user in the users table. For every user, the newest message involving him should be displayed, no matter if that newest message was sent or recieved by him.
You could use a correlated subquery to get that value for each user ID:
SELECT id,
username,
(SELECT MAX(id)
FROM messages
WHERE sender = users.id
OR recipient = users.id
) AS last_message_id
FROM users
This is also possible with GROUP BY.
First join the two table together, then create a group for each user:
SELECT users.id,
MAX(messages.id)
FROM users
JOIN messages ON users.id = messages.sender OR
users.id = messages.recipient
GROUP BY users.id
SELECT year , COUNT(*) AS Count
FROM Movie
WHERE Movie.MID NOT IN
(SELECT DISTINCT m.MID
FROM Movie m
JOIN M_Cast m_c ON m.MID = m_c.MID
JOIN Person p_1 ON m_c.PID = p_1.PID
AND p_1.Gender='Male')
AND Movie.MID IN
(SELECT DISTINCT m.MID
FROM Movie m
JOIN M_Cast m_c ON m.MID = m_c.MID
JOIN Person p_1 ON m_c.PID = p_1.PID
AND p_1.Gender='Female')
GROUP BY year;

Get result from different tables - join

I have following tables in my DB
CREATE TABLE [author_details] (
[_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
[name] TEXT NOT NULL,
[surname] TEXT NOT NULL,
[middle_name] TEXT NULL
);
CREATE TABLE [authors] (
[_id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[book_id] INTEGER NOT NULL,
[author_id] INTEGER NOT NULL
);
CREATE TABLE [books] (
[_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
[title] TEXT NOT NULL,
[publisher_id] INTEGER NOT NULL,
[isbn] VARCHAR(10) UNIQUE NULL,
[ean] VARCHAR(13) UNIQUE NULL,
[pages] INTEGER DEFAULT '0' NULL,
[year] INTEGER NOT NULL,
[edition] TEXT NULL
);
CREATE TABLE [publishers] (
[_id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[name] TEXT NOT NULL
);
I want a list of all books with details, I've used following query:
SELECT b.title,b.isbn,b.ean,b.year,b.pages,b.edition,
CASE
WHEN ad.middle_name IS NULL
THEN ad.name||" "||ad.surname
ELSE ad.name||" "||ad.middle_name||" "||ad.surname
END AS author, p.name
FROM books AS b, authors AS a, author_details AS ad, publishers AS p
INNER JOIN authors, author_details, publishers ON b._id=a.book_id AND ad._id=a.author_id AND b.publisher_id=p._id
GROUP BY b._id
It returns All books but only one author for books with multiple authors. How to write the query to get all authors per book?
To get the values from all records in a group, you have to use the group_concat function:
SELECT b.title,b.isbn,b.ean,b.year,b.pages,b.edition,
group_concat(CASE
...
END) AS author, p.name
FROM ...
Additionally, you need to use the correct join syntax.
In your query, you are joining every table twice, which results in lots up duplicate records.
There are two equivalent syntaxes for joins.
Either use a plain list of tables, and WHERE:
...
FROM books AS b,
authors AS a,
author_details AS ad,
publishers AS p
WHERE b._id = a.book_id
AND a.author_id = ad._id
AND b.publisher_id = p._id
...
or use the JOIN operator for each join, with a join condition for each join:
...
FROM books AS b
JOIN authors AS a ON b._id = a.book_id
JOIN author_details AS ad ON a.author_id = ad._id
JOIN publishers AS p ON b.publisher_id = p._id
...
Try to use group_concat():
SELECT b.title,b.isbn,b.ean,b.year,b.pages,b.edition,
GROUP_CONCAT(CASE
WHEN ad.middle_name IS NULL
THEN ad.name||" "||ad.surname
ELSE ad.name||" "||ad.middle_name||" "||ad.surname
END) AS author,
p.name
FROM
.........

Resources