How can I aggregate data based on sub query results - sql-server

I have a sql query like this:
SELECT (SUM(DURATIONSECS) / 3600.00) AS LaborHrs,
(SELECT LABORLEV2 t2 FROM LABOR WHERE LABORID = t1.LABORID) As Dept
FROM Table1 t1
WHERE DTM BETWEEN 'datetime1' AND 'datetime2' AND
(SELECT LABORLEV1 FROM LABOR WHERE LABORID = t1.LABORID) = '100'
AND PAYCODEID='1'
Group BY LABORID
This gives me the correct data like this:
LaborHrs Dept
90.5000000 office
1033.2500000 retail
522.2500000 retail
217.5000000 misc
1145.5000000 misc
40.0000000 retail
However I need the results to be aggregated if the dept name is the same for instance I need the sum of all labor hours of "retail" and "misc" to be in the same column. I have tried grouping by Dept, but it did not recognize that column name.

I rewrote your query based on what I understand of your question, but I'm pretty suspicious of this part:
DTM BETWEEN 'datetime1' AND 'datetime2'
I assume that it is a datetime variable or number that you would substitute in.
If that is the case, I guess here might be the answer.
SELECT (SUM(DURATIONSECS) / 3600.00) AS LaborHrs,
, l1.LABORLEV2 AS Dept
FROM Table1 t1
JOIN LABOR l1 ON l1 ON l1.LABORID=t1.LABORID
WHERE DTM BETWEEN 'datetime1' AND 'datetime2' AND l1.LABORLEV1='100'
AND t1.PAYCODEID='1'
Group BY t1.LABORID, l1.LABORLEV2

If you want to Group some column, the column can't be a subselect, so you will have to rewrite the query using JOINS.
By what I understant of your query, you can join the tables Tabl1 and LABOR and move your conditions to a single WHERE statement, something like this:
SELECT
l.LABORLEV2 AS Dept,
(SUM(t1.DURATIONSECS) / 3600.00) AS LaborHrs
FROM Table1 t
INNER JOIN LABOR l ON t.LABORID=l.LABORID
WHERE
l.LABORLEV1='100' AND
t1.PAYCODEID='1' AND
t1.DTM BETWEEN 'datetime1' AND 'datetime2'
GROUP BY l.LABORLEV2

Related

SELECT statement with sub-query

Instructions:
Business case: The accounting department would like a reporting of the top ten vendors with their last invoice date and average invoice amount.
Write a SELECT statement that returns three columns:
VendorName (from the Vendors table)
LatestInv (summary function that returns the last entry from InvoiceDate)
AverageInv: (summary function that returns the average from InvoiceTotal)
Hint: you will need to join two tables before joining to the derived table (the subquery)
Subquery portion: SELECT statement that returns the top ten VendorID and AverageInv (same name and function as described in the outer query). Group the results by the appropriate column and sort the results by AverageInv from largest to smallest. Correlate the subquery as BestVendors and join it to the correct table (where both share a key field).
Group the outer query by the appropriate column and sort the results by LatestInv
most recent to oldest
My code
SELECT VendorName, MAX(InvoiceDate) AS LatestInv, AVG(InvoiceTotal) AS AverageInv
FROM Vendors v JOIN
(SELECT TOP 10 VendorID, AVG(InvoiceTotal) AS AverageInv
FROM Invoices
GROUP BY VendorID
ORDER BY AverageInv DESC) AS BestVendors
ON v.VendorID = BestVendors.VendorID
GROUP BY VendorName
ORDER BY LatestInv
MAX(InvoiceDate) has a red line under it as well as AVG(InvoiceTotal) because they are from the Invoices table. Not the Vendors. However if I use FROM Invoices in the outer query then VendorName won't be recognized? How do I fix this and get the result set that this question is looking for?
Also these pics show some sample data from the Invoices and Vendors Table
Try this:
SELECT VendorName, BestVendors.LatestInv, BestVendors.AverageInv
FROM Vendors v
INNER JOIN
(
SELECT TOP 10 VendorID
,AVG(InvoiceTotal) AS AverageInv
,MAX(InvoiceDate) AS LatestInv
FROM Invoices
GROUP BY VendorID
ORDER BY AverageInv DESC
) AS BestVendors
ON v.VendorID = BestVendors.VendorID
ORDER BY LatestInv DESC

Insert Into TABLE from 3 separate tables

I am getting my face kicked in....
I have a total of 4 tables
1. Business (BusinessID, CustomerID, BusName, Territory)
2. Customer (CustomerID, Name)
3. Sales (BusinessID, CustomerID, Territory, Jan, Feb, Mar, Apr, May, Jun)
4. Performance (this is the table I want the info in)
I've already created the table to have the following columns, BusinessID, CustomerID, BusName, Name, Territory, Jan,Feb,Mar,Apr,May,Jun
Every time I try to insert its not properly joining and I am getting a bunch of errors "multi-part identifier could not be bound"
insert into Performance (BusinessID, CustomerID, BusName, Name, Territory, January2018, February2018, March2018, April2018, May2018, June2018)
select Business.BusinessID, Customer.CustomerID, Business.BusName, Customer.Name, Sales.Territory, Sales.January2018, Sales.February2018, Sales.March2018, Sales.April2018, Sales.May2018, Sales.June2018
from Business A
inner join Customer B ON a.CustomerID = b.CustomerID
inner join Sales C ON b.CustomerID = c.CustomerID;
Due to this error I had to do 3 seperate insert into and that caused a bunch of nulls....
face palm is happening and could use some advice.
Image: enter image description here
Thanks,
VeryNew2SQL
You have used table ALIASES, so you have to use those aliases in you SELECT
A for Business, B for Customer and C for Sales.
Read about ALIASES here.
select A.BusinessID, B.CustomerID, A.BusName, B.Name, C.Territory, C.January2018, C.February2018, C.March2018, C.April2018, C.May2018, C.June2018
from Business A
inner join Customer B ON a.CustomerID = b.CustomerID
inner join Sales C ON b.CustomerID = c.CustomerID;
When you create a table alias in your FROM and JOIN clauses, you need to refer to the aliases in your SELECT statement and not the actual table names.
Alternatively, leave your SELECT statement as it is, and adjust your table names to remove the alias. You'll then need the join conditions to refer to your actual table names, rather than the alias. So for example;
select Business.BusinessID, Customer.CustomerID, Business.BusName, Customer.Name, Sales.Territory, Sales.January2018, Sales.February2018, Sales.March2018, Sales.April2018, Sales.May2018, Sales.June2018
from Business
inner join Customer ON Business.CustomerID = Customer.CustomerID
inner join Sales ON Customer.CustomerID = Sales.CustomerID;
Even just try running the SELECT statement above first to make sure you get the query correct before trying it in your insert.

Create a view with sum total across two tables grouped by date (SQL Server 2008)

I currently have a view like this:
CREATE VIEW dbo.audit
WITH schemabinding
AS
SELECT
CONVERT(date, DateAdded) AS dt,
COUNT_BIG(*) AS cnt
FROM
dbo.Table1
GROUP BY
CONVERT(date, DateAdded)
Which returns:
dt cnt
-----------------
3/13/2015 5000
3/12/2015 1324
I'm trying to get a sum total count from both tables grouped by date into a single view. Is this possible?
i.e.
Table 1 Table 2
dt cnt | dt cnt
3/13/2015 5000 | 3/13/2015 1000
3/12/2015 1324 | 3/12/2015 1
To:
View 1
dt cnt
3/13/2015 6000
3/12/2015 1325
It would be nice to keep this in a single view. As it's just a running total of how many new items got added. Any ideas?
Assuming that there are two views and depending on relationship between these two views (based on values from dt columns: View1.dt and View2.dt) you could use a INNER/LEFT/RIGHT or FULL JOIN thus:
SELECT ISNULL(v1.dt, v2.dt) AS dt, ISNULL(v1.cnt, 0) + ISNULL(v2.cnt, 0) AS cnt
FROM dbo.View1 v1 /*INNER/LEFT/RIGHT*/ FULL JOIN dbo.View2 v2 ON v1.dt = v2.dt
I've used FULL JOIN because I assumed that there are values in View1.dt column that doesn't exist in View2.dt column and also there are values in View2.dt column that doesn't exist in View1.dt. More, some dt values could exist in both columns(views).
Note: I assume that second view has the same definition but it uses Table2 as data source: FROM dbo.Table2.
Assuming your data is such that there can be days missing from the tables it's easier to handle the dates by creating a table of dates (one row per day) so that you can join the tables using it, like this:
CREATE VIEW dbo.audit WITH schemabinding AS
select
Dates.Date as dt,
count_big(Table1.date) as ct_1,
count_big(Table2.date) as ct_2
from
Dates
left outer join Table1 on convert(date, Table1.Date) = Dates.Date
left outer join Table2 on convert(date, Table2.Date) = Dates.Date
group by
Dates.Date
SQL Fiddle: http://sqlfiddle.com/#!6/bf116/3
If the tables are huge there might be some problems with performance because SQL Server isn't going to use index for the dates because there is a conversion to date -- and this is in case you have a where clause on the view. If you need something like that an inline table value function might work better because then you can have variables for the date ranges.
If I understand your question correctly, try something like this:
CREATE VIEW dbo.audit WITH schemabinding AS
SELECT CONVERT(Table1.date,DateAdded) AS Table1_dt,
COUNT_BIG(Table1.*) AS Table1_cnt,
CONVERT(Table1.date,DateAdded) AS Table2_dt,
COUNT_BIG(Table2.*) AS Table2_cnt
FROM dbo.Table1 INNER JOIN dbo.Table2 ON(Table1.date = Table2.Date)
GROUP BY CONVERT(Table1,DateAdded)
This solution assumes the same column names in both tables and also the same dates to be selected.

Distinct count over two tables. SQL

I'm very new to SQL, I apologize if something doesn't make sense!
I have two tables each of which has a column 'client_nbr'. Some of the client_nbrs will overlap in the two tables. I'm needing to count the number of people with a certain value in column 'age' that is in both tables. For example, the results should have something like
age - 5 count - 3,000
And that will only count a client number once, even if it is in both tables.
When I do this for one table I run:
Select age, count(distinct(client_nbr))
From table1
Group by age
I tried to follow the example here: http://www.sqlservercurry.com/2011/07/sql-server-distinct-count-multiple.html?m=1
Using:
Select table1.age,table2.age,
Count(distinct(table1.client_nbr)) as total
From table1,table2
Where table1.client_nbr=table2.client_nbr
Group by table1.age,table2.age
It didn't work out though. The total count was less than when I run a distinct count on just table1.
Thank you in advance!
Try this instead:
SELECT age, COUNT(DISTINCT client_nbr) AS Total
FROM
(
SELECT age, client_nbr FROM table1
UNION ALL
SELECT age, client_nbr FROM table2
) AS t
GROUP BY age
You are using an implicit inner join in your query meaning only the values contained in both tables are returned. Use an outer join to get all the values in both tables
Select table1.age,table2.age,
Count(distinct(table1.client_nbr)) as total
From table1 FULL OUTER JOIN table2 ON table1.age = table2.age
Group by table1.age,table2.age

SQL Server last date

Is there an option for getting the row with the highest date without joining the same table and use max(date) ?? Is Top1 order by desc a valid option ?
I use SQL Server 2000. And performance is important.
edit:
Table1:
columns: part - partdesc
Table 2:
columns: part - cost - date
select a.part,partdesc,b.cost
left join( select cost,part
right join(select max(date),part from table2 group by part) maxdate ON maxdate.date = bb.date
from table2 bb ) b on b.part = a.part
from table1
I don't know if the code above works but that is the query I dislike. And seems to me inefficient.
Here's a somewhat simplified query based on your edit.
SELECT
a.part,
a.partdesc,
sub.cost
FROM
Table1 A
INNER JOIN
(SELECT
B.part,
cost
FROM
Table2 B
INNER JOIN
(SELECT
part,
MAX(Date) as MaxDate
FROM
Table2
GROUP BY
part) BB
ON bb.part = b.part
AND bb.maxdate = b.date) Sub
ON sub.part = a.part
The sub-sub query will hopefully run a little bit quicker than your current version since it'll run once for the entire query, not once per part value.
SELECT TOP 1 columnlist
FROM table
ORDER BY datecol DESC
is certainly a valid option, assuming that your datacols are precise enough that you get the results needed (in other words, if it's one row per day, and your date reflects that, then sure. If it's several rows per minute, you may not be precise enough).
Performance will depend on your indexing strategy and hardware.

Resources