Count and group by in a referenced table, selecting other attributes - sql

I have two tables: account_table and branch_table.
create table branch_table(
id int,
address varchar
);
create table account_table(
accid int,
balance int,
type varchar,
branch_ref ref branch_type
branch_ref SCOPE IS branch_table
);
How do I list the number of accounts of type 'saving' per branch, and select the address of this branch as well?

For each branch there will be unique address and we can do group by operation on both of those columns or we can do group by on branchid and then take max of address this doesnt change anything. And also need to do group by on account type to get type wise details.
SELECT b.id, b.address,COUNT(accid) no_of_accts
FROM account_table a
INNER JOIN
branch_table b
ON a.branch_ref = b.id
WHERE a.type = 'saving'
GROUP BY b.id,b.address,a.type;

SELECT b.address,COUNT(*) AS no_of_accts
FROM account_table a
INNER JOIN
branch_table b
ON a.branch_ref = b.id
WHERE a.type = 'saving'
GROUP BY b.address;

Related

SQL query - Return 0 for the column if no record found

I will like to see the specific fields returns with 0 value when there is no record found.
Below are my SQL queries that I have tried so far.
SELECT Customer, Address, Number of lines, Date
FROM table_name
WHERE Date = '30-5-2022' AND Customer IN (A, B, C)
What it returns is only 1 row as below.
Customer
Address
Number of Lines
Date
A
3
RF
30-5-2022
But what I expected to see is:
Customer
Address
Number of Lines
Date
A
UK
33
30-5-2022
B
0
0
30-5-2022
C
0
0
30-5-2022
The customer B and C has no record on 30-5-2022 but I will still need to see the rows but certain columns can be 0.
Please advise if anything that I have missed out? Thanks a lot!
Try below query:
SELECT A.Customer, ISNULL(B.Address, 0),
ISNULL(B.[Number of lines],0), ISNULL(B.Date, '30-05-2022') Date
FROM
(
SELECT DISTINCT Customer
FROM table_name
) A
LEFT JOIN table_name B
ON A.Customer = B.Customer
AND B.Date = '30-5-2022'
This will output all the customers present in the table. You can filter the customers with WHERE clause in the end of the above query based on your requirement.
dbfiddle Link
Assuming customers are in one table (cust) and other stuff in another table (table_name) and they are connected with an id called custid, you need some sweet, sweet left join action, such as:
SELECT c.Customer, c.Address, isnull([Number of lines],0), d.Date
FROM cust c left join table_name d on c.custid = d.custid and
d.Date = '30-5-2022' where
c.Customer IN ('A', 'B', 'C')
You need to put A, B, C in a table and left-join the main table to it. All other conditions must then go in the ON clause not the WHERE.
You can use a virtual VALUES clause for this
SELECT Customer, Address, Number of lines, Date
FROM (VALUES
('A'),
('B'),
('C')
) v(Customer)
LEFT JOIN table_name tn ON tn.Customer = v.Customer
AND tn.Date = '30-5-2022';
Alternatively you can pass in a Table Valued Parameter, or use a table variable. Don't forget to add a primary key.
DECLARE #tmp TABLE (Customer varchar(100) PRIMARY KEY);
INSERT #tmp(Customer) VALUES
('A'),
('B'),
('C');
SELECT Customer, Address, Number of lines, Date
FROM #tmp v
LEFT JOIN table_name tn ON tn.Customer = v.Customer
AND tn.Date = '30-5-2022';

Find values from table whose column value determines which column from another table to be used for lookup

I have 2 tables with no relationship defined at DDL.
CREATE TABLE SOURCES(
ID VARCHAR2(25),
SOURCE VARCHAR(2),
VALUE_ID(VARCHAR2(25),
LAST_UPDATED TIMESTAMP);
CREATE TABLE USERS(
ID VARCHAR2(25),
USER_ID VARCHAR(25),
CLIENT_ID VARCHAR(25));
I need to find all those rows from table sources given an input value for column VALUE_ID. VALUE_ID is set to USERS.USER_ID or USERS.CLIENT_ID based on the SOURCE column of that row.
IF SOURCE = 'A' THEN VALUED_ID = USERS.USER_ID ELSE USERS.CLIENT_ID
Any help resolving this would be much appreciated.
You can use a CASE statement in your join:
Select *
FROM SOURCES S
INNER JOIN USERS U
on S.Value_ID = CASE WHEN S.SOURCE='A' then U.USER_ID ELSE U.CLIENT_ID END
Just use AND and OR in the join condition:
SELECT *
FROM sources s
INNER JOIN users u
ON ( (s.source = 'A' AND s.value_id = u.user_id )
OR (s.source <> 'A' AND s.value_id = u.client_id))

Is there a way to select this name from more than one table?

I need to select the item name and the vendor name for each item that belongs to the vendor with a rating bigger than 4. And I can't find a way, I know it's something with joins but the 2 of them have the same column name.
CREATE TABLE venedors(
id int PRIMARY KEY,
name varchar2(20),
rating int)
CREATE TABLE items(
id int PRIMARY KEY,
name varchar2(20),
venedorId int references venedors(id))
If i understanded your problem.
Select items.name as itemName, venedors.name as vendorName
from items
inner join venedors
on items.venedorId = venedors.id
where venedors.rating > 4
If you want get all the vendors irrespective whether there are items associated with vendors or not, then try with left join as shown below:
Select v.name as vendorName, i.name as itemName
from venedors v
left join items i
on i.venedorId = v.id
where v.rating > 4

Sql query to find select customer that bought in the specific company address

Here is my table
CREATE TABLE Customer
(
ID CHAR(50),
Customer_FName CHAR(50),
Customer_Lname CHAR(50)
);
CREATE TABLE Buying
(
Customer_ID CHAR(50),
Product_ID CHAR(50),
Order_Time CHAR(50)
);
CREATE TABLE Product
(
ID CHAR(50),
Name CHAR(50),
Address CHAR(50)
);
I am trying to find all customers who bought a product with their company's address in 'Burwood' and list the customer's ID, names, product ID, product name and product address
Select
Buying.Customer_ID, Buying.Product_ID, Product.ID,
Product.Name, Customer.ID,
Customer.Customer_FName, Customer.Customer_Lname
from
((Buying
inner join
Product on Buying.Product_ID = Product.ID)
inner join
Customer on Buying.Customer_ID = Customer.ID)
where
Product.Address like '%Burwood%';
I want to combine three table but It shows 'no rows selected'.
I also give a sample data table
Any reason why you have chosen CHAR as the datatype for all columns of all tables? For CHAR based columns, DBs tend to pad the values up to the column width defined. That said, it is not why you are not getting result. You may want to check if during insert you are adding any extra space or non-printable characters in IDs resulting into failed inner joins.
I suggest change the fields to VARCHAR instead, validate your inserts and then query just as I demonstrated below. You will start getting result, as I am..
CREATE TABLE Customer (
ID varchar(50),
Customer_FName varchar(50),
Customer_Lname varchar(50)
);
CREATE TABLE Buying (
Customer_ID varchar(50),
Product_ID varchar(50),
Order_Time varchar(50)
);
CREATE TABLE Product (
ID varchar(50),
Name varchar(50),
Address varchar(50)
);
insert into customer values('10001', 'John', 'Smith');
insert into Buying values('10001', '772', '2016/09/01');
insert into Product values('772', 'Telephone', '22 Ave, Burwood');
select b.product_id, p.name, b.customer_id, c.customer_fname, c.customer_lname
from buying b
join product p on b.product_id = p.id
join customer c on b.customer_id = c.id
where lower(p.address) like '%burwood%'
Please try this, it works for me:
Select B.Customer_ID, B.Product_ID, P.ID, P.Name, C.ID, C.Customer_FName, C.Customer_Lname
from Buying B
INNER JOIN Product P ON B.Product_ID = P.ID
INNER JOIN Customer C ON B.Customer_ID = C.ID
WHERE P.Address LIKE '%Burwood%'
Try this:
SELECT C.*,B.*, P.*
FROM Customer C,Buying B, Product P
WHERE B.Product_ID=P.ID
AND B.Customer_ID=C.ID
AND P.Address LIKE '%Burwood%';

Get latest record from second table left joined to first table

I have a candidate table say candidates having only id field and i left joined profiles table to it. Table profiles has 2 fields namely, candidate_id & name.
e.g. Table candidates:
id
----
1
2
and Table profiles:
candidate_id name
----------------------------
1 Foobar
1 Foobar2
2 Foobar3
i want the latest name of a candidate in a single query which is given below:
SELECT C.id, P.name
FROM candidates C
LEFT JOIN profiles P ON P.candidate_id = C.id
GROUP BY C.id
ORDER BY P.name;
But this query returns:
1 Foobar
2 Foobar3
...Instead of:
1 Foobar2
2 Foobar3
The problem is that your PROFILES table doesn't provide a reliable means of figuring out what the latest name value is. There are two options for the PROFILES table:
Add a datetime column IE: created_date
Define an auto_increment column
The first option is the best - it's explicit, meaning the use of the column is absolutely obvious, and handles backdated entries better.
ALTER TABLE PROFILES ADD COLUMN created_date DATETIME
If you want the value to default to the current date & time when inserting a record if no value is provided, tack the following on to the end:
DEFAULT CURRENT_TIMESTAMP
With that in place, you'd use the following to get your desired result:
SELECT c.id,
p.name
FROM CANDIDATES c
LEFT JOIN PROFILES p ON p.candidate_id = c.id
JOIN (SELECT x.candidate_id,
MAX(x.created_date) AS max_date
FROM PROFILES x
GROUP BY x.candidate_id) y ON y.candidate_id = p.candidate_id
AND y.max_date = p.created_date
GROUP BY c.id
ORDER BY p.name
Use a subquery:
SELECT C.id, (SELECT P.name FROM profiles P WHERE P.candidate_id = C.id ORDER BY P.name LIMIT 1);