database and ER diagram for this scenario - sql

A company serves many clients through selling different products. These products are sold by sales persons who then take 0.1% out of every deal they make. Sales persons are not paid monthly salary but are on basic pay, i.e, 1200 + commission in sales. There are total 12 employees , 10 sales persons and 2 managers. Each manager has 5 sales persons working under him. The company requires the following information:
each sales record made by sales person with date
sales person total income every month
bonus to those sales persons who make sale more than 1 million rupees in any year
no. of sales persons having gmail account

The main problem i'm struggling with is to calculate the salary of the
sales person. I've got products cost in the products table and how
many products a sales person sold in the sales-record table. But this
salary column is in salesperson table. How can i calculate salary by
using data from two different tables?
If you can calculate the dynamic % and the static salary, then all you have to do is to use UNION ALL
SQL Fiddle
MS SQL Server 2014 Schema Setup:
Query 1:
SELECT sum(t.salary) annual_salary
FROM
(
-- the select for the dynamic part
select (15500000*0.001) AS salary -- FROM table
union all
-- the select for the static one
select 30000 AS salary -- FROM table
) AS t
Results:
| annual_salary |
|---------------|
| 45500 |

Related

SQL - How to solve this challenging problem?

I have two tables
First table - ticket history:
customer_id
ticket_price
transportation
company_id
1
$342.21
Plane
D7573
1
$79.00
Car
G2943
1
$91.30
Car
M3223
2
$64.00
Car
K2329
3
$351.00
Plane
H2312
3
$354.27
Plane
P3857
4
$80.00
Car
N2938
4
$229.67
Plane
J2938
5
$77.00
Car
L2938
2nd table - companies and corresponding vehicles:
company_id
vehicle
D7573
Boeing
G2943
Coach
M3223
Shuttle
K2329
Shuttle
H2312
Airbus
P3857
Boeing
N2938
Minibus
J2938
Airbus
L2938
Minibus
Z3849
Airbus
A3848
Minibus
If a customer took both plane and car, then they are "mixed". Otherwise they are "plane" or "car" customers. How can I get the result below?
# shuttle took
Avg ticket price per customer
# of customers
mixed
??????????????
????????????????????????????
??????????????
plane
??????????????
????????????????????????????
??????????????
car
??????????????
????????????????????????????
??????????????
Your title is misleading, you need to specify which part you are having problem.
May not be the best answer. Tested in MYSQL env, sql fiddle
select transportation,
sum(no_of_shuttle) as no_of_shuttle_took,
round(avg(ticket_price), 2) as avg_price_per_customer,
count(customer_id) as no_of_customer
from (
select
customer_id,
'mixed' as transportation,
count(transportation) as no_of_shuttle,
sum(ticket_price) as ticket_price
from tickets
group by customer_id
having count(distinct transportation) > 1
union all
select
customer_id,
transportation,
count(transportation) as no_of_shuttle,
sum(ticket_price) as avg_ticket_price
from tickets
group by customer_id
having count(distinct transportation) = 1
) t
group by transportation
I am using subqueries to aggregate
customers with multiple distinct transportation type
customers with single distinct transportation type
Then I union these two results into one result set to further calculate the number of customers, number of shuttle took and average ticket price per customer. Note that I am rounding the price to 2 decimal places.
SQL Server using a common table expression:
;WITH cte1 as (
SELECT customer_id,CASE when count(distinct(transportation))>1 THEN 'Mixed' ELSE MAX(transportation) END as transportation, AVG(ticket_price) as avg_ticket_price,SUM(CASE WHEN vehicle='Shuttle' THEN 1 ELSE 0 END) as shuttle
FROM history as a
JOIN vehicle as b ON a.company_id=b.company_id
GROUP BY customer_id)
SELECT transportation,COUNT(DISTINCT(customer_id)) as num_cust, AVG(avg_ticket_price) as avg_ticket_price,sum(shuttle) as shuttle
FROM cte1
GROUP BY transportation

Why did the 'NOT IN' work but not the 'NOT EXISTS'?

I've been trying to improve my SQL and was playing around with a 'NOT EXISTS' function. I needed to find the names of salespeople who did not have any sales to company 'RED'.
I tried this and it did not work:
SELECT DISTINCT
sp.name
FROM salesperson sp
WHERE NOT EXISTS (
SELECT
ord.sales_id
FROM
company cmp
LEFT JOIN orders ord
on cmp.com_id=ord.com_id
WHERE cmp.name = 'RED')
This query ran but returned a NULL. Then I changed it to this and it worked fine:
SELECT DISTINCT
sp.name
FROM salesperson sp
WHERE sp.sales_id NOT IN (
SELECT
ord.sales_id as sales_id
FROM
company cmp
left join orders ord
on cmp.com_id=ord.com_id
WHERE cmp.name = 'RED')
Can someone explain why 'NOT EXISTS' did not work in this instance?
.
.
.
.
.
.
Just in case, here is the exercise in full:
Given three tables: salesperson, company, orders
Output all the names in the table salesperson, who didn’t have sales to company 'RED'.
Table: salesperson
sales_id
name
salary
commission_rate
hire_date
1
John
100000
6
4/1/2006
2
Amy
120000
5
5/1/2010
3
Mark
65000
12
12/25/2008
4
Pam
25000
25
1/1/2005
5
Alex
50000
10
2/3/2007
The table salesperson holds the salesperson information. Every salesperson has a sales_id and a name.
Table: company
com_id
name
city
1
RED
Boston
2
ORANGE
New York
3
YELLOW
Boston
4
GREEN
Austin
The table company holds the company information. Every company has a com_id and a name.
Table: orders
order_id
order_date
com_id
sales_id
amount
1
1/1/2014
3
4
100000
2
2/1/2014
4
5
5000
3
3/1/2014
1
1
50000
4
4/1/2014
1
4
25000
The table orders holds the sales record information, salesperson and customer company are represented by sales_id and com_id.
expected output
name
Amy
Mark
Alex
Explanation:
According to order '3' and '4' in table orders, it is easy to tell only salesperson 'John' and 'Pam' have sales to company 'RED', so we need to output all the other names in the table salesperson.
I think your two queries are totally different.
NOT EXISTS - this will return data when that subquery doesn't return data. Which will always return some data so you will always get null. You need to join this subquery with the main query using WHERE sp.sales_id = ord.sales_id AND cmp.name = 'RED'
NOT IN - this is what you need for your purpose. You can see that it's clearly giving you data for not in (subquery) condition.
The equivalent NOT EXISTS requires a correlation clause:
SELECT sp.name
FROM salesperson sp
WHERE NOT EXISTS (SELECT ord.sales_id
FROM company cmp JOIN
orders ord
ON cmp.com_id = ord.com_id
WHERE sp.sales_id = ord.sales_id AND
cmp.name = 'RED'
);
Neither the NOT IN nor NOT EXISTS versions requires a LEFT JOIN in the subquery. In fact, the LEFT JOIN somewhat defeats the purpose of the logic.
Without the correlation clause, the subquery runs and it will return rows if any cmp.name is 'RED'. That appears to be the case and so NOT EXISTS always returns false.

SQL Group by prevents summing across multiple records

I am trying to sum the amount paid across multiple entries in the Payment table and show who the buyers were for that Order
so if two people made payments on one order it would show their combined payments and show who the people who made the payment were. So if Bob and Sue made 10 dollar payments on a 30 dollar bill it would show
Order Buyer Paid Owes
1 Bob 20 10
1 Sue 20 10
but i'm currently at
Order Paid Owes
1 20 10
How do I add in the buyers? possibly with a join?
Currently I have.
Select Order.Orderid, sum(Payment.amount) as "Paid", Order.Price-sum(Payment.amount) as "Owes"
from order, payment
where payment.orderId = order.orderid
group by (order.orderid, order.price)
payment has a buyerId and orderid as foreign keys since it is an m to n relation.
As you mention in your comment when you join the buyer it does not give you the desired output which is the sum of all payments. To get the buyers and the sum of all payments joining another instance of the payments table and using that to calculate the sum will do the trick.
SELECT
Order.Orderid,
Buyer.Name,
SUM(PaymentSum.amount) AS 'Paid',
Order.Price-SUM(PaymentSum.amount) AS 'Owes',
FROM
Order
JOIN Payment
ON Order.Orderid = Payment.Orderid
JOIN Buyer
ON Payment.BuyerId Buyer.BuyerId
JOIN Payment AS PaymentSum
ON Order.Orderid = PaymentSum.Orderid
GROUP BY
Order.Orderid,
Order.Price,
Buyer.Name

How can I produce rows that sum subgroups of rows, without grouping?

Let's say I have a table like this:
ID Income Expenses
-------------------------
1 $1000 $200
1 $2000 $400
2 $500 $200
2 $100 $60
I'd like to add one row per ID that sums the ID's Income and Expenses. For example:
ID Income Expenses
-------------------------
1-SUM $3000 $600
1 $1000 $200
1 $2000 $400
2-SUM $600 $260
2 $500 $200
2 $100 $60
Is this possible with SQL? I read about OVER and PARTITION BY but that'll add a new column, not a new row. Might a UNION be the best way to go here?
Try this
create table yourtable(id int,income int,expenses int)
insert into yourtable values (1,100,200),(1,150,250),(2,200,300),(2,250,350)
with CTE
as
(select ID,sum(income) as income,sum(expenses) as expenses,1 as isSum
from yourtable
group by id
)
select * from (
select *,0 as isSum from yourtable
union all
select * from CTE ) as t
order by id,issum
output
Using GROUP BY:
SQLFiddleDemo
CREATE TABLE tab(id INT , income INT , expenses INT);
INSERT INTO tab(id, income, expenses)
VALUES (1, 1000, 200),(1, 2000, 400),(2, 500, 200),(2, 100, 60)
SELECT id,
[income] = SUM(income),
[expenses] = SUM(expenses),
[grouping_level] = GROUPING_ID(id, income, expenses) /* 0 - actual data , 3 - group based on column income, expenses*/
FROM tab
GROUP BY GROUPING SETS ((id), (id,income, expenses))
Why grouping is useful:
Using GROUPING SETS gives great flexibility for instance when you want total sum use: GROUP BY GROUPING SETS ((id), (id,income, expenses), ())
GROUPING SETS can be combined with ROLLUP/CUBE.
GROUPING_ID indicates grouping level.
Number works like binary. GROUPING(a, b, c) if b i c is used for grouping you get 011B => 3

how to view the name of credit and debit in same table from other table

I have to tables, table accounts and table entities, the credit and debit are number = id in table account,
i want to write a query and the result is the name of credit number and the name of debit number and date and value from table entities
some data from tables:
table entities:
id credit debit value date
1 100 101 5000 01/01/2014
table accounts:
id name
100 Mark
101 Jone
this some data from my database. All what I need a query to show this result:
1, Mark, Jone, 5000, 01/01/2014
You'll need to join the accounts table twice (once for the credit name, and once for the debit name):
SELECT
e.id,
credit_account.name AS CreditName,
debit_account.name AS DebitName,
e.value,
e.date
FROM entities AS e
JOIN accounts AS credit_account ON e.credit = credit_account.id
JOIN accounts AS debit_account ON e.debit = debit_account.id
This query produces this output:
id CreditName DebitName value date
----------- -------------------- -------------------- ----------- ----------
1 Mark Jone 5000 2014-01-01
It assumes there is a value in both the credit and debit columns for each row in the entities table. If one of them can be missing you might want to useLEFT JOINinstead to get a null value in the column with the missing value.
Sample SQL Fiddle