SQL Server Stored Procedure Combining 2 table results - sql-server

I have two tables:
CustomerTransaction
Id (int auto int)
CustomerName (varchar)
CustomerNumber (int)
Date (date)
WeeklyAmount (int)
Customers:
CustomerName (varchar)
CustomerNumber (int)
CustomerType (int)
CustomerDate (date)
This database is not normalized, and I can not change it. The CustomerName and what I need to do:
I need a result that will show one table with all of the information from Customers for each row that matches customer number. In CustomerTransaction, I am merely grouping all of the total sums per CustomerName of their amount.
I am using:
Select
CustomerNumber, SUM (WeeklyAmount) as Total
from
Customers.RECORDS
GROUP BY
CustomerNumber;
To get the sum of each CustomerNumber. The problem is that I can not include CustomerName in the group by. Sometimes the name of customers change over time. I was told to grab the data from Customers and it to the result above and match the CustomerNumbers
The problem is that I do not know that with a stored procedure. Anyone know how this is done?
I need all the rows matched.

Select
CustomerNumber, SUM (WeeklyAmount) as Total from
Customers.RECORDS GROUP BY CustomerNumber;
What is Customers.RECORDS? That's a bit confusing. Apart from that, I'd answer
SELECT
c.*,
sq.Total
FROM
(
SELECT
CustomerNumber,
SUM(WeeklyAmount) AS Total
FROM
CustomersTransaction
GROUP BY CustomerNumber
) sq
INNER JOIN Customers c ON c.CustomerNumber = sq.CustomerNumber
If that's not what you're looking for, you have to rephrase your question. It's a bit hard to understand where the actual problem is. Usually I'd write the query a bit different, but this should deal with the non-normalization issue.

Select
Trans.CustomerNumber, C.CustomerName, Trans.SUM (WeeklyAmount) as Total
from
CustomerTransaction Trans
join
Customers C
on
Trans.CustomerNumber=C.CustomerNumber
GROUP BY
Trans.CustomerNumber,C.CustomerName

Related

T-SQL: GROUP BY, but while keeping a non-grouped column (or re-joining it)?

I'm on SQL Server 2008, and having trouble querying an audit table the way I want to.
The table shows every time a new ID comes in, as well as every time an IDs Type changes
Record # ID Type Date
1 ae08k M 2017-01-02:12:03
2 liei0 A 2017-01-02:12:04
3 ae08k C 2017-01-02:13:05
4 we808 A 2017-01-03:20:05
I'd kinda like to produce a snapshot of the status for each ID, at a certain date. My thought was something like this:
SELECT
ID
,max(date) AS Max
FROM
Table
WHERE
Date < 'whatever-my-cutoff-date-is-here'
GROUP BY
ID
But that loses the Type column. If I add in the type column to my GROUP BY, then I'd get get duplicate rows per ID naturally, for all the types it had before the date.
So I was thinking of running a second version of the table (via a common table expression), and left joining that in to get the Type.
On my query above, all I have to join to are the ID & Date. Somehow if the dates are too close together, I end up with duplicate results (like say above, ae08k would show up once for each Type). That or I'm just super confused.
Basically all I ever do in SQL are left joins, group bys, and common table expressions (to then left join). What am I missing that I'd need in this situation...?
Use row_number()
select *
from ( select *
, row_number() over (partition by id order by date desc) as rn
from table
WHERE Date < 'whatever-my-cutoff-date-is-here'
) tt
where tt.rn = 1
I'd kinda like know how many IDs are of each type, at a certain date.
Well, for that you use COUNT and GROUP BY on Type:
SELECT Type, COUNT(ID)
FROM Table
WHERE Date < 'whatever-your-cutoff-date-is-here'
GROUP BY Type
Basing on your comment under Zohar Peled answer you probably looking for something like this:
; with cte as (select distinct ID from Table where Date < '$param')
select [data].*, [data2].[count]
from cte
cross apply
( select top 1 *
from Table
where Table.ID = cte.ID
and Table.Date < '$param'
order by Table.Date desc
) as [data]
cross apply
( select count(1) as [count]
from Table
where Table.ID = cte.ID
and Table.Date < '$param'
) as [data2]

SQLite - Return 0 if null

I have an assignment in Database Management Systems in which I have to write queries for given problems.
I have 4 problems, of which I solved 3 and stuck with the last one.
Details:
Using version 1.4 of the Chinook Database
(https://chinookdatabase.codeplex.com/).
SQLite DB Browser
Chinook Sqlite AutoIncrementPKs.sqlite file​ in the directory with Chinook files is the database I am working on
Problem Statement:
Write a query to generate a ranked list of employees based upon the amount of money brought in via customer invoices for which they were the support representative. The result set (see figure below) should have the following fields (in order) for all employees (even those that did not support any customers): ID (e_id), first name (e_first name), last name (e_last_name), title (e_title), and invoice total (total_invoices). The rows should be sorted by the invoice total (greatest first), then by last name (alphabetically), then first name (alphabetically). The invoice total should be preceded by a dollar sign ($) and have two digits after the decimal point (rounded, as appropriate); in the case of employees without any invoices, you should output a $0.00, not NULL. You may find it useful to look at the IFNULL, ROUND, and PRINTF functions of SQLite.
Desired Output:
My Query:
Select Employee.EmployeeId as e_id,
Employee.FirstName as e_first_name,
Employee.LastName as e_last_name,
Employee.Title as e_title,
'$' || printf("%.2f", Sum(Invoice.Total)) as total_invoices
From Invoice Inner Join Customer On Customer.CustomerId = Invoice.CustomerId
Inner Join Employee On Employee.EmployeeId = Customer.SupportRepId
Group by Employee.EmployeeId
Having Invoice.CustomerId in
(Select Customer.CustomerId From Customer
Where Customer.SupportRepId in
(Select Employee.EmployeeId From Employee Inner Join Customer On Employee.EmployeeId = Customer.SupportRepId)
)
order by sum(Invoice.Total) desc
My Output:
As you can see, the first three rows are correct but the later rows are not printed because employees don't have any invoices and hence EmployeeID is null.
How do I print the rows in this condition?
I tried with Coalesce and ifnull functions but I can't get them to work.
I'd really appreciate if someone can modify my query to get matching solutions.
Thanks!
P.S: This is the schema of Chinook Database
It often happens that it is simpler to use subqueries:
SELECT EmployeeId,
FirstMame,
LastName,
Title,
(SELECT printf("...", ifnull(sum(Total), 0))
FROM Invoice
JOIN Customer USING (CustomerId)
WHERE Customer.SupportRepId = Employee.EmployeeId
) AS total_invoices
FROM Employee
ORDER BY total_invoices DESC;
(The inner join could be replaced with a subquery, too.)
But it's possible that you are supposed to show that you have learned about outer joins, which generate a fake row containing NULL values if a matching row is not found:
...
FROM Employee
LEFT JOIN Customer ON Employee.EmployeeId = Customer.SupportRepId
LEFT JOIN Invoice USING (CustomerID)
...
And if you want to be a smartass, replace ifnull(sum(...), 0) with total(...).

SQL Aggregate function issues using DISTINCT function

I'm needing help with a question that I've been racking my brain on for two days now (Almost), on this assignment. I'm still pretty new to SQL and I'm just struggling.
I DO NOT WANT THE ANSWER!! I'm just looking for help getting going in the right direction.
Here is the question:
Write a SELECT statement that answers this question: Which customers have ordered more than one product? Return these columns:
The email address from the Customers table
The count of distinct products from the customer’s orders
Here is what I have so far:
SELECT Customers.CustomerID,
Count(DISTINCT ProductID) AS ProductsCount
FROM Customers
INNER JOIN Orders
ON Customers.CustomerID = Orders.CustomerID
JOIN Products
ON Products.ProductID = OrderItems.ProductID
GROUP BY Customers.CustomerID,
Orders.CustomerID
But I keep getting this error:
Msg 4104, Level 16, State 1, Line 2
The multi-part identifier "OrderItems.ProductID" could not be bound.
The structure of the three tables in play here is.
The Customer table has an Emailaddress and CustomerID column.
The Orders table has CustomerID and OrderID columns.
The Products table has ProductID column.
The OrderItems table has OrderID, ProductID, and Quantity columns.
Any Help would be really really helpful!
Thanks!
Fix the syntax as suggested by joining to the OrderItems table and in order to look for something more than once, you need to use group by field1, field2, etc. having count(field) > 1. You are almost there.
You are almost there :-)
You forgot to join OrderItems.
You don't need the table Products in this query (you don't want to see anything from that table; you get the product count from OrderItems).
To limit by aggregates (as by the number of products here) use HAVING.
To group by Orders.CustomerID is superfluous, as it equals Customers.CustomerID.
Here is a tip to find the answer,
find the orders which has has more than one item in OrderItems
table by using having clause with Count() aggregate and Group by orderID.
so from the first step you will have the orders that have more than
one item and count of products in every order. next join the first step result with
order table to get the customerid.
next join the second step result with customers table to get the
customers information who bought more than one one product in single
order with count.

The extract total distinct count for two columns from a table in SQL Server

In the table PRODUCT, contains the attribute:
P_CODE, P_DESCRIPT, P_INDATE, P_QOH, P_MIN, P_PRICE, P_DISCOUNT, V_CODE
I am trying to find how to display the total distinct count of P_code for each V_code type in the product table.
I have written this but it shows as a error, can't quite figure out why.
SELECT COUNT(*)
FROM
(
SELECT DISTINCT P_CODE,V_CODE
FROM PRODUCT
)
Much appreciated for your help.
You can use count distinct with a group by clause:
SELECT V_code, COUNT (DISTINCT P_code)
FROM product
GROUP BY V_code

Unable to understand the SQL code

I am finding it difficult to understand the code below. Can you give me a logical flow of how the code works ?
The question -
suppose you want to display the total number of orders placed by every customer in your Customers table. Orders are stored in the Orders table along with the appropriate customer ID.
The steps -
retrieve the list of customers from the customers table.
for each customer retrieved, count the number of associated orders in the Orders table.
The solution -
SELECT cust_name, cust_state,
(SELECT COUNT(*)
FROM Orders
WHERE Orders.cust_id = Customers.cust_id
)
AS order_nos
FROM Customers
ORDER BY cust_name
I am unable to understand the count(*) part inside the brackets. Please help me to figure it out.
Thanks.
It's just counting the number of rows. In this case, that's the number of orders per customer. The alternative COUNT(column_name) gives you the number of rows where column_name isn't null.
Equivalent without the sub-query (using a group instead):
SELECT cust_name, cust_state, COUNT(orders.cust_id) order_nos
FROM Customers
LEFT OUTER JOIN Orders on Customers.cust_id = Orders.cust_id
GROUP BY cust_name, cust_state
ORDER BY cust_name
It's called a correlated subquery. Essentially, for each customer, you're going to get a count of how many orders that customer has. The "magic" is in the WHERE Orders.cust_id = Customers.cust_id clause in the subquery. That's the part that correlates this result to your main query. It's saying "take the cust_id from the main query and now find the count of orders where the cust_id is that cust_id".

Resources