Building/Creating SQL Metrics from the table - sql

I have a table:
SELECT aaa.sr_nbr,
aaa.inst_nbr,
bb.country,
bb.sr_control_type,
bb.it_tran_code,
ccc.cust_name,
ccc.cust_nbr
FROM tablea1 aaa
INNER JOIN tablea2 bb
ON aaa.inst_id=bb.inst_id AND aaa.item_id=bb.item_id
LEFT JOIN table3 ccc
ON bb.inst_id=ccc.inst_id AND bb.item_id=ccc.item_id
WHERE ccc.cust_name NOT LIKE '%EXP%'
AND ccc.cust_name NOT LIKE '%RMAA%' mt;
Now, I have created, separately, queries for metrics, like:
SELECT mt.sr_nbr,
mt.inst_nbr,
mt.country,
mt.sr_control_type,
mt.it_tran_code,
mt.cust_name,
mt.cust_nbr
COUNT(mt.sr_nbr) as cnt_nbr
FROM mt
WHERE mt.it_tran_code <> 'D'
GROUP BY 1,2,3,4,5,6,7;
or the another one:
SELECT t_2.sr_nbr,
t_2.inst_nbr,
t_2.country,
t_2.sr_control_type,
t_2.it_tran_code,
t_2.cust_name,
t_2.cust_nbr
SUM(t_2.sn_dup) AS sn_dup_sum
FROM (
SELECT
t_1.sr_nbr,
t_1.inst_nbr,
t_1.country,
t_1.sr_control_type,
t_1.it_tran_code,
t_1.cust_name,
t_1.cust_nbr
COUNT(t_1.sr_nbr) AS sn_dup
FROM
(
SELECT
mt.sr_nbr,
mt.inst_nbr,
mt.country,
mt.sr_control_type,
mt.it_tran_code,
mt.cust_name,
mt.cust_nbr
FROM mt
WHERE ccc.cust_name NOT LIKE '%EXP%'
AND ccc.cust_name NOT LIKE '%RMAA%'
) AS t_1
GROUP BY 1,2,3,4,5,6,7
HAVING
COUNT(t_1.sr_nbr) > 1
) AS t_2
GROUP BY 1,2,3,4,5,6,7;
and so on... I have about 10 similar metrics.
Now, I do not know the best way how to "put" those query metrics within the main table/query.

You can insert results of a SELECT query into a table if you are able to fill the INSERT statement correctly.
Example:
INSERT INTO Customers (CustomerName, City, Country)
SELECT SupplierName, City, Country FROM Suppliers
WHERE Country='Germany';
Source: https://www.w3schools.com/sql/sql_insert_into_select.asp
Make sure the amount and types of the results matches the columns you're trying to insert.

Related

Count Distinct values in one column based on other column

I am trying to count distinct values on Z_l based on value by using with clause. Sample data exercise included below.
please look at the picture, the distinct values of Z_l based on X='ny'
with distincz_l as (select ny.X, ny.z_l o.cnt From HOPL ny join (select X, count(*) as cnt from HOPL group by X) o on (ny.X = o.Z_l)) select * from HOPL;
You don't even need a WITH clause, since you just need one single sentence:
SELECT z_l, count(1)
FROM hopl
WHERE x='ny'
GROUP BY z_l
;

Show unique ID's in a table with all extra info

SELECT Personeelsnummer, Achternaam, Voornaam, Departement, SubDep, SubSubDep, FTE, RedenUitDienst, Anciennitëitsdatum, GeldigOp, Schrapping, Ancienniteit, Positie, Nieveau, OmschrijfingStatuut
FROM tbl_Worker
GROUP BY Personeelsnummer
OR
SELECT (DISTINCT Personeelsnummer), Achternaam, Voornaam, Departement, SubDep, SubSubDep, FTE, RedenUitDienst, Anciennitëitsdatum, GeldigOp, Schrapping, Ancienniteit, Positie, Nieveau, OmschrijfingStatuut
FROM tbl_Worker
GROUP BY Personeelsnummer
I have a worker table with 49000 records, this includes a 'snapshot' from all workers EVERY month. But what I need is a table with all employees the company 'ever' had but only once. so I tried to wright the query's show above but they are not working.
So what I need is a query that shows all unique 'Personeelsnummers' with all the extra information about these persons.
what does work is this: SELECT DISTINCT Personeelsnummer FROM tbl_Worker ==> this gives me a table with 1200 records but only the numbers but I need all the extra information.
Instead of GROUP BY, use WHERE to get the first or last record:
SELECT w.*
FROM tbl_Worker as w
WHERE monthcol = (SELECT MAX(w2.monthcol)
FROM tbl_Worker as w2
WHERE w2.Personeelsnummer = w.Personeelsnummer
);
You would use MIN() to get the first month's record. My Dutch is a bit weak, so I don't know which column refers to the date for the record.
For performance, you want an index on tbl_Worker(Personeelsnummer, GeldigOp):
create index idx_tbl_worker_Personeelsnummer_GeldigOp on tbl_Worker(Personeelsnummer, GeldigOp);
EDIT:
Or you can do it with a JOIN:
SELECT w.*
FROM tbl_Worker as w INNER JOIN
(SELECT Personeelsnummer, MAX(GeldigOp) as max_GeldigOp
FROM tbl_Worker
GROUP BY Personeelsnummer
) as ww
ON ww.Personeelsnummer = w.Personeelsnummer and ww.max_GeldigOp = w.GeldigOp;
You're looking for a group by:
select *
from table
group by field1
Which can occasionally be written with a distinct on statement:
select distinct on field1 *
from table
As seen in this topic.

SQL: multiple counts from same table

I am having a real problem trying to get a query with the data I need. I have tried a few methods without success. I can get the data with 4 separate queries, just can't get hem into 1 query. All data comes from 1 table. I will list as much info as I can.
My data looks like this. I have a customerID and 3 columns that record who has worked on the record for that customer as well as the assigned acct manager
RecID_Customer___CreatedBy____LastUser____AcctMan
1-------1374----------Bob Jones--------Mary Willis------Bob Jones
2-------1375----------Mary Willis------Bob Jones--------Bob Jones
3-------1376----------Jay Scott--------Mary Willis-------Mary Willis
4-------1377----------Jay Scott--------Mary Willis------Jay Scott
5-------1378----------Bob Jones--------Jay Scott--------Jay Scott
I want the query to return the following data. See below for a description of how each is obtained.
Employee___Created__Modified__Mod Own__Created Own
Bob Jones--------2-----------1---------------1----------------1
Mary Willis------1-----------2---------------1----------------0
Jay Scott--------2-----------1---------------1----------------1
Created = Counts the number of records created by each Employee
Modified = Number of records where the Employee is listed as Last User
(except where they created the record)
Mod Own = Number of records for each where the LastUser = Acctman
(account manager)
Created Own = Number of Records created by the employee where they are
the account manager for that customer
I can get each of these from a query, just need to somehow combine them:
Select CreatedBy, COUNT(CreatedBy) as Created
FROM [dbo].[Cust_REc] GROUP By CreatedBy
Select LastUser, COUNT(LastUser) as Modified
FROM [dbo].[Cust_REc] Where LastUser != CreatedBy GROUP By LastUser
Select AcctMan, COUNT(AcctMan) as CreatePort
FROM [dbo].[Cust_REc] Where AcctMan = CreatedBy GROUP By AcctMan
Select AcctMan, COUNT(AcctMan) as ModPort
FROM [dbo].[Cust_REc] Where AcctMan = LastUser AND NOT AcctMan = CreatedBy GROUP By AcctMan
Can someone see a way to do this? I may have to join the table to itself, but my attempts have not given me the correct data.
The following will give you the results you're looking for.
select
e.employee,
create_count=(select count(*) from customers c where c.createdby=e.employee),
mod_count=(select count(*) from customers c where c.lastmodifiedby=e.employee),
create_own_count=(select count(*) from customers c where c.createdby=e.employee and c.acctman=e.employee),
mod_own_count=(select count(*) from customers c where c.lastmodifiedby=e.employee and c.acctman=e.employee)
from (
select employee=createdby from customers
union
select employee=lastmodifiedby from customers
union
select employee=acctman from customers
) e
Note: there are other approaches that are more efficient than this but potentially far more complex as well. Specifically, I would bet there is a master Employee table somewhere that would prevent you from having to do the inline view just to get the list of names.
this seems pretty straight forward. Try this:
select a.employee,b.created,c.modified ....
from (select distinct created_by from data) as a
inner join
(select created_by,count(*) as created from data group by created_by) as b
on a.employee = b.created_by)
inner join ....
This highly inefficient query may be a rough start to what you are looking for. Once you validate the data then there are things you can do to tidy it up and make it more efficient.
Also, I don't think you need the DISTINCT on the UNION part because the UNION will return DISTINCT values unless UNION ALL is specified.
SELECT
Employees.EmployeeID,
Created =(SELECT COUNT(*) FROM Cust_REc WHERE Cust_REc.CreatedBy=Employees.EmployeeID),
Mopdified =(SELECT COUNT(*) FROM Cust_REc WHERE Cust_REc.LastUser=Employees.EmployeeID AND Cust_REc.CreateBy<>Employees.EmployeeID),
ModOwn =
CASE WHEN NOT Empoyees.IsManager THEN NULL ELSE
(SELECT COUNT(*) FROM Cust_REc WHERE AcctMan=Employees.EmployeeID)
END,
CreatedOwn=(SELECT COUNT(*) FROM Cust_REc WHERE AcctMan=Employees.EmployeeID AND CReatedBy=Employees.EMployeeID)
FROM
(
SELECT
EmployeeID,
IsManager=CASE WHEN EXISTS(SELECT AcctMan FROM CustRec WHERE AcctMan=EmployeeID)
FROM
(
SELECT DISTINCT
EmployeeID
FROM
(
SELECT EmployeeID=CreatedBy FROM Cust_Rec
UNION
SELECT EmployeeID=LastUser FROM Cust_Rec
UNION
SELECT EmployeeID=AcctMan FROM Cust_Rec
)AS Z
)AS Y
)
AS Employees
I had the same issue with the Modified column. All the other columns worked okay. DCR example would work well with the join on an employees table if you have it.
SELECT CreatedBy AS [Employee],
COUNT(CreatedBy) AS [Created],
--Couldn't get modified to pull the right results
SUM(CASE WHEN LastUser = AcctMan THEN 1 ELSE 0 END) [Mod Own],
SUM(CASE WHEN CreatedBy = AcctMan THEN 1 ELSE 0 END) [Created Own]
FROM Cust_Rec
GROUP BY CreatedBy

SQL query - Selecting distinct values from a table

I have a table in which i have multiple entries against a FK. I want to find out the value of FK which do not have certain entries e.g
my table has following entries.
PK----------------FK-----------------Column entries
1----------------100-----------------ab1
2----------------100-----------------ab2
3----------------100-----------------ab4
4----------------200-----------------ab1
5----------------200-----------------ab2
6----------------200-----------------ab3
7----------------300-----------------ab1
8----------------300-----------------ab2
9----------------300-----------------ab3
10---------------300-----------------ab4
Now, from this table i want to filter all those FK which do not have ab3 or ab4 in them. Certainly, i expect distinct values i.e. in this case result would be FK= 100 and 200.
The query which i am using is
select distinct(FK)
from table1
where column_entries != 'ab3'
or column_entries != 'ab4';
Certainly, this query is not fetching the desired result.
try the following :-
select distinct fk_col from table1
minus
(select distinct fk_col from table1 where col_entry='ab3'
intersect
select distinct fk_col from table1 where col_entry='ab4')
This will show all those FKs which do not have 'ab3' and 'ab4'. i.e. 100 and 200 in your case
The below script may be the solution if I got your question in a right way.
SELECT DISTINCT(TableForeignKey)
FROM Test
WHERE TableForeignKey NOT IN (
SELECT T1.TableForeignKey
FROM Test T1 INNER JOIN Test T2 ON T1.TableForeignKey = T2.TableForeignKey
WHERE T1.TableEntry = 'ab3' AND T2.TableEntry = 'ab4')
SQLFiddle Demo
You could use GROUP BY with conditional aggregation in HAVING:
SELECT FK
FROM table1
GROUP BY FK
HAVING COUNT(CASE column_entries WHEN 'ab3' THEN 1 END) = 0
OR COUNT(CASE column_entries WHEN 'ab4' THEN 1 END) = 0
;
The two conditional aggregates count 'ab3' and 'ab4' entries separately. If both end up with results greater than 0, then the corresponding FK has both 'ab3' and 'ab4' and is thus not returned. If at least one of the counts evaluates to 0, then FK is considered satisfying the requirements.

MySQL intersection in subquery

I'm trying to create a filter for a list (of apartments), with a many-to-many relationship with apartment features through the apartsments_features table.
I would like to include only apartments that have all of some features (marked 'Yes' on a form) excluding all the ones that have any of another set features (marked 'No'). I realized too late that I couldn't use INTERSECT or MINUS in MySQL.
I have a query that looks something like:
SELECT `apartments`.* FROM `apartments` WHERE `apartments`.`id` IN (
SELECT `apartments`.`id` FROM `apartments` INTERSECT (
SELECT `apartment_id` FROM `apartments_features` WHERE `feature_id` = 103
INTERSECT SELECT `apartment_id` FROM `apartments_features` WHERE `feature_id` = 106
) MINUS (
SELECT `apartment_id` FROM `apartments_features` WHERE `feature_id` = 105 UNION
SELECT `apartment_id` FROM `apartments_features` WHERE `feature_id` = 107)
)
ORDER BY `apartments`.`name` ASC
I'm pretty sure there's a way to do this, but at the moment my knowledge is restricted to little more than simple left and right joins.
A slightly different way of doing it:
select a.*
from apartments a
join apartments_features f1
on a.apartment_id = f1.apartment_id and f1.feature_id in (103,106) -- applicable features
where not exists
(select null from apartments_features f2
where a.apartment_id = f2.apartment_id and f2.feature_id in (105,107) ) -- excluded features
group by f1.apartment_id
having count(*) = 2 -- number of applicable features
You could try something like this:
SELECT apartment_id
FROM
(
SELECT apartment_id
FROM apartments_features
WHERE feature_id IN (103, 106)
GROUP BY apartment_id
HAVING COUNT(*) = 2
) T1
LEFT JOIN
(
SELECT apartment_id
FROM apartments_features
WHERE feature_id IN (105, 107)
) T2
ON T1.apartment_id = T2.apartment_id
WHERE T2.apartment_id IS NULL
Join the result of this query to the apartments table to get the name, etc.