show result from one table - sql

good day, i have these 3 tables...i.e.;
customer table
cust_id cust_name sales_employee
1 abc 1
2 cde 1
3 efg 2
transaction table
order_num cust_id sales_employee
1001 1 1
1002 2 2
sales_employee table
sales_employee employee name
1 john doe
2 jane doe
how can i show the employee name on both customer table and transaction table?
notice how the sales_employee can change per transaction, it does not necessarily have to be the same per customer.
please help.

To select customers with sales person name
select
C.*, E.employee_name
from
Customers as C
inner join Sales_Employees as E on E.sales_employee = C.sales_employee
To select transactions with customer name and salesperson name (at the point in time of the transaction)
select
T.*,
E.employee_name as Trans_employee,
C.cust_name,
EC.employee_name as Cust_employee
from
Transactions as T
inner join Sales_Employees as E on E.sales_employee = T.sales_employee
inner join Customers as C on C.cust_id= T.cust_id
inner join Sales_Employees as EC on EC.sales_employee = C.sales_employee
This code is meant to guide you, you will need to adjust it to match your table and field names.

Related

How to inner join same table with different conditions?

I need to get contact information where employee id is null and not null. How do I join the same table with these different conditions. I need the information to populate a report with both employee information and person accompanied them to a event. Here is the query I have so far.
select events.id, (persons.firstname+' '+ persons.lastname) as employee
from events
inner join eventscontacts on events.id = eventcontacts.events_id
inner join contacts on eventcontacts.contact_id = contacts.id
inner join persons on contacts.person_id = person.id
Eventcontacts table
Id ContactType_id contact_id event_id
1 1 1 300
2 2 3 300
Contact type is 1 for employee and 2 for non emplopyees
contacts table
Id person_id employee_id
1 100 200
2 101 201
3 102 NULL
4 103 202
5 104 203
Person table
Id firstname lastname
100 John Stewart
101 Greg Larry
102 Kim Hans
103 Gloria June
104 Dan Duke
Result table
ID employee accompany
300 John Stewart Kim Hans
right now, I have information of all the employees for the event. I want the people who accompanied these person for the events. Their employee id is null in the contacts table. How do I join the contacts table again here?
An inner join will return only the rows that exist in both tables, where it seems like you want all the rows from the contacts table including the rows that don't match due to them lacking an employee id.
If you use an outer join, it will return rows that exist in contacts AND in events like an inner join but ALSO rows that ONLY exist in events and rows that ONLY exist in contacts.
In the case that I am explaining this poorly, I recommend you read this to help explain:
https://mode.com/sql-tutorial/sql-outer-joins/
If you can successfully use an outer join you will get all the visitors in one table regardless of having an id or not.

Eliminate database rows based on mod dates

I have an issue grabbing data from two tables base on a single field in one of the tables The field does not exist in both tables.
Example:
Table 1 (call it invoices):
invoice email customer_name original_bill invoice_status
1 a#g.com bob 5.00 P
2 a#g.com harry 23.00 P
3 a#g.com sally 4.00 P
4 b#g.com loretta 14.00 P
5 b#g.com hamish 74.00 P
Table 2 (customer invoice edits):
invoice email date_last_modified_timestamp mod_status mod_amount
1 a#g.com 2019-05-01 A 3.00
1 a#g.com 2019-04-01 D
3 b#g.com 2019-10-25 A
What I want
a list of all invioces and their mods but I only wish each invoice to appear once in the list. based on the latest date in Table two.
example:
invoice email customer_name original_bill invoice_status date_last_modified_timestamp mod_status mod_amount
1 a#g.com bob 5.00 P 2019-05-01 A 3.00
2 a#g.com harry 23.00 P
3 a#g.com sally 4.00 P 2019-10-25 A
4 b#g.com loretta 14.00 P
5 b#g.com hamish 74.00 P
How im pulling it now:
select invoice, email, customer_name, original bill, invoice status, max(date_last_modified_timestamp), mod status, mod_amount
from table one
left join on table1.invoice = table 2.invoice
group by
invoice, email, customer_name, original bill, invoice status, max(date_last_modified_timestamp), mod status, mod_amount
I've tried a gazzillion variation to no avail.
What i get
i do get accurate results, but those results inclues a duplicate row containing each invoice that has been modified. I only want one invoice per row. I want the one that's been modified last. Is this even possible? What am I doing wrong?
You can join and use a correlated subquery for filtering:
select i.*, e.*
from invoices i
inner join customer_invoice_edits e
on e.invoice = i.invoice
and e.date_last_modified_timestamp = (
select max(date_last_modified_timestamp)
from customer_invoice_edits e1
where e1.invoice = e.invoice
)
This will give you one record per row in the invoices table that has a match in customer_invoice_edits, along with the latest corresponding record in customer_invoice_edits.
If some invoices have no corresponding record in the dependant table, they will not appear in the resultset. If you do want to see them, then you can use a left join instead.
Is this what you want?
select
invoice,
email
from (
select
invoice,
email,
mod_status,
mod_amount,
date_last_modified_timestamp,
row_number() over (
partition by invoice, email
order by date_last_modified_timestamp desc
) rn
from table2
)
where rn=1
I'm pretty sure you want this field-by-field. Here is an example:
select i.invoice,
nz( (select top (1)
from invoice_edits as ie
where ie.invoice = i.invoice and ie.email is not null
), i.email
) as email,
nz( (select top (1)
from invoice_edits as ie
where ie.invoice = i.invoice and ie.mod_amount is not null
), i.original_bill
) as original_bill,
. . .
from invoices as i;

Group Join between three tables to get the percentage

I have three tables Attendance, Employee, Sector
Employee Table
EmiId -Name -SectorId
123 ABC 1
231 BCD 2
125 WER 1
Attendance
AttId -EmpId -Dt
1 123 12/12/2014 9:00
2 231 12/12/2014 10:00
Sector
SectorId -SectorName
1 North Sector
2 East Sector
my query is
SELECT COUNT(Attendance.Emp_Id) as AttCount,(select COUNT(*) from Employee) as EmpCount
FROM Employee INNER JOIN
Sector ON Employee.SectorId = Sector.SectorId INNER JOIN
Attendance ON Employee.EmpId = Attendance.EmpId
group by Sector.SectorId
and i keep getting same number of employees for both instead so the (select COUNT(*) from Employee)- EmpCount seems to be incorrect.I keep getting the same number for both the sectors. Although the Attcount seems to work fine.
Please help. Thanks in advance.
You just making select count from the same table - do not expect other results.
Perhaps someone could do it better
SELECT COUNT(Attendance.Emp_Id),COUNT(case when Employee.empid=attendance.attid then 1 else 0 end)
FROM Employee JOIN Sector ON Employee.SectorId = Sector.SectorId
LEFT JOIN Attendance ON Employee.EmpId = Attendance.Emp_Id
group by Sector.SectorId
Maybe you need LEFT JOIN with Attendance
SELECT COUNT(Attendance.Emp_Id),(select COUNT(*) from Employee)
FROM Employee JOIN Sector ON Employee.SectorId = Sector.SectorId
LEFT JOIN Attendance ON Employee.EmpId = Attendance.EmpId
group by Sector.SectorId

Cross-multiplying table

I have this SQL code and I want to show the sum of each item on its charge slip and on their receipt:
select item_description, sum(receipt_qty) as Samp1, sum(chargeSlip_qty) as Samp2
from Items inner join Receipt_Detail on (Receipt_Detail.item_number =
Items.item_number)
inner join ChargeSlip_Detail on (ChargeSlip_Detail.item_number =
Items.item_number)
group by item_description
It produces this output:
Acetazolamide 2681 1730
Ascorbic Acid 1512 651
Paracetamol 1370 742
Silk 576 952
But it should be:
Acetazolamide 383 173
Ascorbic Acid 216 93
Paracetamol 274 106
Silk 96 238
What's wrong with my code?
Since you are joining tables, you might have a one-to-many relationship that is causing the problem when you then get the sum(). So you can use subqueries to get the result. This will get the sum() for the receipt and chargeslip for each item_number and then you join that back to your items table to get the final result:
select i.item_description,
r.Samp1,
c.Samp2
from Items i
inner join
(
select sum(receipt_qty) Samp1,
item_number
from Receipt_Detail
group by item_number
) r
on r.item_number = i.item_number
inner join
(
select sum(chargeSlip_qty) Samp2,
item_number
from ChargeSlip_Detail
group by item_number
) c
on c.item_number = i.item_number
Do the GROUP BYs first, per Item_Number, so you don't multiply out rows from Receipt_Detail and ChargeSlip_Detail. That is, you generate the SUM values per Item_Number before JOINing back to Items
select
I.item_description,
R.Samp1,
C.Samp2
from
Items I
inner join
(SELECT item_number, sum(receipt_qty) as Samp1
FROM Receipt_Detail
GROUP BY item_number
) R
on (R.item_number = I.item_number)
inner join
(SELECT item_number, sum(chargeSlip_qty) as Samp2
FROM ChargeSlip_Detail
GROUP BY item_number
) C
on (C.item_number = I.item_number)
A left join returns rows from the left table, and for each row in the left table, all matching rows in the right table.
So for example:
create table Customers (name varchar(50));
insert Customers values
('Tim'),
('John'),
('Spike');
create table Orders (customer_name varchar(50), product varchar(50));
insert Orders values (
('Tim', 'Guitar'),
('John', 'Drums'),
('John', 'Trumpet');
create table Addresses (customer_name varchar(50), address varchar(50));
insert Addresses values (
('Tim', 'Penny Lane 1'),
('John', 'Abbey Road 1'),
('John', 'Abbey Road 2');
Then if you run:
select c.name
, count(o.product) as Products
, count(a.address) as Addresses
from Customers c
left join Orders o on o.customer_name = c.name
left join Addresses a on a.customer_name = c.name
group by name
You get:
name Products Addresses
Tim 1 1
John 4 4
Spike 0 0
But John doesn't have 4 products!
If you run without the group by, you can see why the counts are off:
select *
from Customers c
left join Orders o on o.customer_name = c.name
left join Addresses a on a.customer_name = c.name
You get:
name customer_name product customer_name address
Tim Tim Guitar Tim Penny Lane 1
John John Drums John Abbey Road 1
John John Drums John Abbey Road 2
John John Trumpet John Abbey Road 1
John John Trumpet John Abbey Road 2
Spike NULL NULL NULL NULL
As you can see, the joins end up repeating each other. For each product, the list of addresses is repeated. That gives you the wrong counts. To solve this problem, use one of the excellent other answers:
select c.name
, o.order_count
, a.address_count
from Customers c
left join
(
select customer_name
, count(*) as order_count
from Orders
group by
customer_name
) o
on o.customer_name = c.name
left join
(
select customer_name
, count(*) as address_count
from Addresses
group by
customer_name
) a
on a.customer_name = c.name
The subqueries ensure only one row is joined per customer. The result is much better:
name order_count address_count
Tim 1 1
John 2 2
Spike NULL NULL

sql query for getting data from two related tables

I have two tables, employee and inventory. One employee can have zero or more inventories.
I would like to list employee information along with at most one inventory information
and count of inventories belongs to one employee.
employee table
emp_num last_name first_name
-----------------------------------
100 john smith
101 mike pet
102 jes lyoid
inventory table
inv_num emp_num
---------------------------
12 100
13 100
15 100
30 102
desired Output
emp_num last_name invnum count(inv_num)
--------------------------------------------------------------------------
100 john 12 3
101 mike - 0
102 jes 30 1
What sql query can I use in this case?
Try this:
SELECT emp_num, last_name, MAX(inv_num) AS invnum, COUNT(inv_num) AS inv_count
FROM employee e LEFT OUTER JOIN inventory i ON e.emp_num = i.emp_num
GROUP BY e.emp_num, e.last_name
You could do something like this
Select E.Emp_Num,
e.Last_name,
MIN(Inv_Num) AS OldestInv,
COUNT(Inv_Num) AS TotalInv
FROM Employee E
LEFT OUTER JOIN Inventory I
(E.Emp_Num = I.Emp_Num)
GROUP BY E.Emp_Num, E.Last_Name
This will give you the minimum invoice number and the total count. The left outer join is the key
SELECT
e.emp_num,
e.last_name,
IFNULL(MAX(i.inv_num),'-') AS 'invnum',
COUNT(i.inv_num) AS 'count(inv_num)'
FROM
employee e LEFT JOIN inventory i
ON e.emp_num = i.emp_num
GROUP BY
e.emp_num, e.last_name