Oracle SQL No Data in series - sql

I have a query result that is almost perfect except for the fact that in the result I don't always have a complete series in my muli-series data that I am trying to eventually show in a report and chart.
NAME MONTH COST
----------------------------------------
name1 2 100
name1 3 80
name2 1 60
name3 2 30
----------------------------------------
Here is query:
select Name, month, count(*) as cost
from table1
group by name, month
order by month, name
What I have here isn't one simple set of data, but a series of data. For each month, I have a set of users and sales.
I can fix this on my application side by doing a few loops and getting the distinct values for Name and Month.
I'd like to learn how to create my Oracle query to get a result set that looks something like this
NAME MONTH COST
----------------------------------------
name1 1 0
name1 2 100
name1 3 80
name2 1 60
name2 2 0
name2 3 0
name3 1 0
name3 2 30
name3 3 0
----------------------------------------

You can do this with a cross join and then a left outer jon:
select n.name, m.month, coalesce(t.cost, 0) as cost
from (select distinct name from table t) n cross join
(select distinct month from table t) m left join
table t
on t.name = n.name and t.month = m.month
order by n.name, m.month;

Related

SQL help i need to find the inventory remaining in my office

In sql help i have 3 tables, table one is asset table which is as follow
id
asset_code
asset_name
asset_group
asset_quantity
1
A001
demo asset
4
5
2
A002
demo asset 2
6
3
and another table is asset_allocation
id
asset_id
allocated_quantity
allocated_location
1
1
2
IT office
2
1
1
main hall
the last table is asset_liquidated which will present assets that are no longer going to be used
id
asset_id
liquidated_quantity
1
1
2
2
1
1
lets say i have 5 computers and i have allocated 3 computers and 1 is no longer going to be used so i should be remaining with 1 computer so now how do i make sql auto generate this math for me
You need to use aggregation and the join your tables -
SELECT id, asset_code, asset_name, asset_group, asset_quantity,
asset_quantity - COALESCE(AA.allocated_quantity, 0) - COALESCE(AL.liquidated_quantity, 0) available_quantity
FROM asset A
LEFT JOIN (SELECT asset_id, SUM(allocated_quantity) allocated_quantity
FROM asset_allocation
GROUP BY asset_id) AA ON A.id = AA.asset_id
LEFT JOIN (SELECT asset_id, SUM(liquidated_quantity) liquidated_quantity
FROM asset_liquidated
GROUP BY asset_id) AL ON A.id = AL.asset_id
This query will give you -1 as available_quantity for asset_id 1 as you have only 5 available, 3 of them are allotted and 3 are liquidated as per your sample data.
Please see if this helps
SELECT
asset_quantity AS Total_Assets
,ISNULL(allocated_quantity, 0) allocated_quantity
,ISNULL(liquidated_quantity, 0) liquidated_quantity
FROM asset
LEFT OUTER JOIN (
SELECT
asset_id, SUM(allocated_quantity) AS allocated_quantity
FROM asset_allocation
GROUP BY asset_id
) asset_allocation2
ON asset_allocation2.asset_id = asset.id
LEFT OUTER JOIN (
SELECT
asset_id, SUM(liquidated_quantity) AS liquidated_quantity
FROM asset_liquidated
GROUP BY asset_id
) asset_liquidated 2
ON asset_liquidated 2.asset_id = asset.id

Select count of total records and also distinct records

I have a table such as this:
PalmId | UserId | CreatedDate
1 | 1 | 2018-03-08 14:18:27.077
1 | 2 | 2018-03-08 14:18:27.077
1 | 3 | 2018-03-08 14:18:27.077
1 | 1 | 2018-03-08 14:18:27.077
I wish to know how many dates were created for Palm 1 and I also wish to know how many users have created those dates for Palm 1. So the outcome for first is 4 and outcome for second is 3
I am wondering if I can do that in a single query as oppose to having to do a subquery and a join on itself as in example below.
SELECT MT.[PalmId], COUNT(*) AS TotalDates, T1.[TotalUsers]
FROM [MyTable] MT
LEFT OUTER JOIN (
SELECT MT2.[PalmId], COUNT(*) AS TotalUsers
FROM [MyTable] MT2
GROUP BY MT2.[UserId]
) T1 ON T1.[PalmId] = MT.[PalmId]
GROUP BY MT.[PalmId], T1.[TotalUsers]
According to first table you could do something like this:
select count(distinct uerid) as N_Users,
count(created_date) as created_date, -- if you use count(*) you consider also rows with 'NULL'
palmid
from your_table
group by palmid
If you want "4" and "3", then I think you want:
SELECT MT.PalmId, COUNT(*) AS NumRows, COUNT(DISTINCT mt.UserId) as NumUsers
FROM MyTable MT
GROUP BY MT.PalmId

Taking Sample in SQL Query

I'm working on a problem which is something like this :
I have a table with many columns but major are DepartmentId and EmployeeIds
Employee Ids Department Ids
------------------------------
A 1
B 1
C 1
D 1
AA 2
BB 2
CC 2
A1 3
B1 3
C1 3
D1 3
I want to write a SQL query such that I take out 2 sample EmployeeIds for each DepartmentID.
like
Employee Id Dept Ids
B 1
C 1
AA 2
CC 2
D1 3
A1 3
Currently I am writing the query,
select
EmployeeId, DeptIds, count(*)
from
table_name
group by 1,2
sample 2
but it gives me total two rows.
Any help?
If the number of departments i know and small you could do a stratified sampling:
select *
from table_name
sample
when DeptIds = 1 then 2
when DeptIds = 2 then 2
when DeptIds = 3 then 2
end
Otherwise a combination of RANDOM and ROW_NUMBER:
select *
from
(
sel EmployeeId, DeptIds, random(1,10000000) as rand
from table_name
) as dt
qualify
row_number()
over (partition by DeptIds
order by rand) <= 2

TSQL - Query for multiple types in multiple rows

I have a table where each address has different types, for each type a row. How to find the addresses where for the exact types i need?
Eg.
ID TypID Street
1 1 Street 1
1 2 Street 1
2 2 Street 2
3 1 Street 3
3 2 Street 3
In the above i need to find addresses which has type 1 and 2. That query result should be adresses with id 1 and 3.
Group by the id and then count the different typeids in the having clause
select id from your_table
where typeid in (1,2)
group by id
having count(distinct typeid) = 2
You can use INTERSECT for this
select id
from tbl
where typid = 1
intersect
select id
from tbl
where typid = 2
although it won't work in mysql if that happens to be the database you're using.
This can be done with a inner join like the below
select y2.*
from <your_table> Y1
JOIN <your_table> Y2
ON Y1.ID = Y2.ID
AND Y1.Type_id in (1,2)
AND Y2.ID in (1,3)

Query to Update Table using another table as information?

I have two tables, Staff and Wages
Staff Contains
id, name, jobID, wage
1 Name1 2
2 Name2 4
3 Name3 1
4 Name4 2
Wages Contains
JobID, Wage
1 1500
2 800
3 1600
4 2000
(There are alot more columns in the actual one I have just took the top 4)
I am missing the wages inside the Staff table, and the wages I need in the staff table are the rates in the Wages table..
So I need a query which would make the Staff table look like:
id, name, jobID, wage
1 Name1 2 800
2 Name2 4 2000
3 Name3 1 1500
4 Name4 2 800
An example Query which I tried was:
UPDATE `Staff`
SET wage = (SELECT wage FROM `Wages`)
WHERE jobID = (Select jobId FROM `Wages`)
Thanks.
In MySQL,
UPDATE Staff a
INNER JOIN Wages b
ON a.jobID = b.JobID
SET a.wage = b.wage
In MSSQL,
UPDATE a
SET a.wage = b.wage
FROM Staff a
INNER JOIN Wages b
ON a.jobID = b.JobID
SOURCE
I would just leave the tables as they are (without the wage column in Staff), in their normalized state, and run this query anytime I need the full set of (denormalized) data:
SELECT s.id, s.name, s.jobID, w.wage
FROM Staff s
LEFT OUTER JOIN Wages w ON s.jobID = w.jobID