Getting customer name based on lowest order from 2 tables - sql-server

I am a beginner learning SQL. I have 2 tables. Trying to get the customer first and last name with least transaction amount - only that 1 row. Been trying different code all day but getting nowhere.
Table 1: Orders
Customer_Id TxnDate Amount
-------------------------------
4001 21-Aug-18 245.99
4002 30-Jan-18 49.99
4003 15-Apr-17 204.87
4001 18-Dec-18 130.88
4004 15-May-17 198.33
4006 4-Feb-17 783.65
Table 2: Customers
Customer_Id AcctOpenDate CustomerFirstName CustomerLastName
--------------------------------------------------------------
4001 7-Jan-16 John Doe
4002 15-Apr-15 Ashley Smith
4003 14-May-14 Carter Jones
4004 17-Sep-16 Ika Gaut
4005 18-Aug-14 Gray Show
4006 25-Oct-15 Kathia Kim
Query:
SELECT
C.CustomerFirstName, C.CustomerLastName, O.Amount
FROM
Customers C
WHERE
Amount = (SELECT MIN(Amount) FROM Orders) Leasttxnamt
INNER JOIN
Customers C ON O.Customer_Id = C.Customer_Id;
Current error produced:
Msg 102, Level 15, State 1, Line 31
Incorrect syntax near 'Leasttxnamt'

Try this..
returns first and last name of customers with lowest transaction amount
select CustomerFirstName,CustomerLastName
from Customer
where Customer_Id in (
SELECT DISTINCT Customer_Id
from Orders
where Amount=(select min(Amount) from orders))

If I understand correctly, you are looking for customer wise MIN amount from the Order table. If this is correct, you can use the following script for your purpose-
This is workable in most of the databases.
SELECT C.CustomerFirstName, C.CustomerLastName, MIN(Amount) min_amount
FROM Customers C
LEFT JOIN Orders O ON O.Customer_Id = C.Customer_Id
GROUP BY C.CustomerFirstName, C.CustomerLastNam

Try the following query :
SELECT Customers.CustomerFirstName ,Customers.CustomerLastName
FROM Customers
JOIN Orders ON Customers.Customer_Id = Orders.Customer_Id
AND Orders.Amount=(
SELECT min(Amount) FROM Orders
WHERE Customers.Customer_Id = Orders.Customer_Id
)

Related

Joining multiple tables and applying aggegate giving wrong result

I have a business case where when a CountryId is passed to my proc, I need to get all the Regions where the Business is set up in that country, All the Active Sales Employees working in that Region, Total sales done by the current active sales employees in that region.
My Region table look like below.
RegionId | Name | CountryId
100 A 1
101 B 4
103 C 1
SalesEmployee Table
Id | EmployeeId | RegionId
1 250 100
2 255 101
3 289 101
Employee Table
EmployeeId | Active
250 1
255 1
289 0
314 1
Sales table
SaleId | EmployeeId| RegionId | Sale
1 100 2 3500
2 101 4 2000
3 100 2 1500
My below query is giving me the correct TotalSales value but the TotalUsers count doesn't match.
Select R.[RegionId], COUNT(SE.[UserId]) AS TotalUsers, SUM(S.[Sales]) AS TotalSales
FROM dbo.[Region] R
INNER JOIN [SalesEmployee] SE
ON R.[RegionId] = SE.[RegionId]
INNER JOIN dbo.[Employee] E
ON E.[EmployeeId] = SE.[EmployeeId]
LEFT JOIN dbo.[Sales] S
ON S.[EmployeeId] = E.[EmployeeId]
WHERE R.[CountryId] = 12 AND E.[Active] = 1
GROUP BY R.[RegionId]
For Ex RegionId 100 has only 7 Active sales employees currently working but the result gives me 89, in my Employee table there can be many more users but few of them can be inactive and few of them may be working in another department, to make sure that the employee is sales employee the employee needs to be present in SalesEmployee table and to check if the Employee is Active I need to check in Employee table.
The problem is 1 single user can have multiple entries on his name in sales table, so when i am joining with Sales table which has multiple entries on a single user then the TotalEmployees count is going up.
So its actually a easy small fix.
Select R.[RegionId], COUNT(DISTINCT(SE.[UserId])) AS TotalUsers, SUM(S.[Sales]) AS TotalSales
FROM dbo.[Region] R
INNER JOIN [SalesEmployee] SE
ON R.[RegionId] = SE.[RegionId]
INNER JOIN dbo.[Employee] E
ON E.[EmployeeId] = SE.[EmployeeId]
LEFT JOIN dbo.[Sales] S
ON S.[EmployeeId] = E.[EmployeeId]
WHERE R.[CountryId] = 12 AND E.[Active] = 1
GROUP BY R.[RegionId]
This small change will give you what you want.
Changing COUNT(SE.[UserId]) to COUNT(DISTINCT(SE.[UserId])) is all you need.

Error on Group by method

I wrote a query to combine records in multiple tables. Tables named by Purchase Order, Purchase Order Item
[ Note: The column names are not original names, it just for a model data]
In purchase order table have the order details like this,
id date vendorid totalitems totalqty grossamnt netamnt taxamt
----------------------------------------------------------------------------
1 03/10/17 00001 2 6 12000 13000 1000
Purchase Order Item table have the order details like this,
poid id productcode qty rate tax(%) taxamnt total
--------------------------------------------------------
1 1 12001 3 6000 2.5 500 6500
2 1 12000 3 6000 2.5 500 6500
My Query is,
select po.POID,po.SupplierId,po.TotalItems from
PurchaseOrder po, PurchaseOrderItem poi where po.POID=poi.POID group by
po.POID, po.SupplierId,po.TotalItems
Query returns,
id vendorid totalitems
--------------------------
1 00001 2
1 00001 2
Expected Output is,
id vendorid totalitems
------------------------
1 00001 2
You are using an outdated join method, have a read here:
ANSI vs. non-ANSI SQL JOIN syntax
You are also joining to another table, but never use it:
select po.POID,po.SupplierId,po.TotalItems
from PurchaseOrder po, PurchaseOrderItem poi
where po.POID=poi.POID
group by po.POID, po.SupplierId,po.TotalItems
Can just be:
select po.POID,po.SupplierId,po.TotalItems
from PurchaseOrder po
group by po.POID, po.SupplierId,po.TotalItem
OR
select DISTINCT
po.POID,
po.SupplierId,
po.TotalItems
from PurchaseOrder po

sql server 2012 merge values from two tables

I have two tables
tblA(sn, ID int pk, name varchar(50), amountA decimal(18,2))
and
tblB(ID int fk, amountB decimal(18,2))
here: tblA occures only once and tblB may occure multiple time
I need the query to display data like:
sn ID name AmountA amountB Balance
1 1001 abc 5000.00 5000.00
2 1002 xyz 10000.00
1002 4000.00 6000.00 (AmountA-AmountB)
3 1003 pqr 15000.00
1003 4000.00
1003 3000.00
1003 2000.00 6000.00 (AmountA-sum(AmountB))
Please ask if any confusion
I tried using lag and lead function but I couldnot get the desire result, Please help.
Since you are using SQL Server 2012, you can use a partition with an aggregate function (SUM):
SELECT t.sn,
t.ID,
t.name,
t.credits AS AmountA,
t.debits AS amountB,
SUM(t.credits - t.debits) OVER (PARTITION BY t.ID ORDER BY t.debits, t.credits) AS Balance
FROM
(
SELECT sn,
ID,
name,
AmountA AS credits,
0 AS debits
FROM tblA
UNION ALL
SELECT 0 AS sn,
ID,
NULL AS name,
0 AS credits,
amountB AS debits
FROM tblB
) t
ORDER BY t.ID,
t.debits,
t.credits
Explanation:
Since the records in tables A and B each represent a single transaction (i.e. a credit or debit), using a UNION query to bring both sets of data into a single table works well here. After this, I compute a rolling sum using the difference between credit and debit, for each record, for each ID partition group. The ordering is chosen such that credits appear at the top of each partition while debits appear on the bottom.

UPDATE SQL Query to update a table based on two dates

i would like to update my query table based on two dates, i tried the following code but it didn't work
UPDATE [Stock Report] INNER JOIN Report ON [Stock Report].ItemID = Report.ItemID SET [Stock Report].Amount = SUM(Report.Amount) WHERE [Date Product Was Made] BETWEEN #AA AND #BB
My two query tables are Report and Stock Report
Report Table
ItemID| Item |Date Product Was Made|Amount|ProductID|Product Name
10 Flour 11/17/2015 100 54 Saltbread
11 Bran Flakes 11/17/2015 100 54 Saltbread
10 Flour 11/17/2015 100 54 Saltbread
11 Bran Flakes 11/17/2015 100 54 Saltbread
What i would like to see in Stock Report Table
ItemID| Item | Start Date | End Date |Amount
10 Flour 11/16/2015 11/25/2015 200
11 Bran Flakes 11/16/2015 11/25/2015 200
The dates can be any two random dates but the table should generate a total based on the amount used in between the date ranges. Wht]at would be the SQL code to complete this process
As EuphoriaGrogi mentioned, you were pretty close.
SELECT ItemID, Item, #AA AS StartDate, #BB AS EndDate, SUM(Amount) AS TotalAmount
FROM (YourReportTableQueryWith#AAAnd#BBParametersHere) AS SubQuery
GROUP BY SubQuery.ItemID,SubQuery.Item
More on GROUP BY here: http://www.w3schools.com/sql/sql_groupby.asp
You tagged with mysql, sql-server and ms-access.
But answers will differ for each case.
Here SQLServer solution:
WITH SumAmount AS (
SELECT
ItemId
,SUM(Report.amount) as sum_amount
FROM
Report
GROUP BY
ItemId
)
UPDATE SR
SET
amount = SA.sum_amount
FROM
[Stock Report] SR
JOIN SumAmount SA ON SR.ItemID = SA.ItemID
WHERE
[Date Product Was Made] BETWEEN #AA AND #BB
Supposed MS Access query (I'm not proficient with MSACCESS, going by http://www.fmsinc.com/microsoftaccess/query/snytax/update-query.html):
UPDATE [Stock Report]
JOIN (
SELECT
ItemId
,SUM(Report.amount) as sum_amount
FROM
Report
GROUP BY
ItemId
) SA ON [Stock Report].ItemID = SA.ItemID
SET
[Stock Report].amount = SA.sum_amount
WHERE
[Date Product Was Made] BETWEEN #AA AND #BB

SQL Server 2008 how to select top [column value] and random record?

I'm using SQL Server 2008, I want select random row record, and the total number of record is depend on another table's column value, how to do this?
My SQL statement is something like this, but wrong..
select top b.number a.name, a.link_id
from A a
left join B b on b.link_id = a.link_id
order by newid()
Here are my tables and the expected result.
Table A:
name link_id
james 100
albert 100
susan 100
simon 101
tom 101
fion 101
Table B:
link_id number
100 2
101 1
Expected result:
when run 1st time, result may be:
name link_id
james 100
susan 100
fion 101
2nd time result may be:
albert 100
susan 100
simon 101
3rd time could be:
james 100
albert 100
fion 101
Explaination
Refer to table B, link_id: 100, number: 2
meaning that Table A should select out 2 random record for link_id = 100
and need to select 1 random record for link_id=101
You can use the ROW_NUMBER() function:
SELECT A.name, A.link_id
FROM(
SELECT name,link_id, ROW_NUMBER()OVER(PARTITION BY link_id ORDER BY NEWID()) rn
FROM dbo.tblA
) AS A
JOIN dbo.tblB AS B
ON A.link_id = B.link_id
WHERE A.rn <= B.number;
Here is a SqlFiddle to show this in action: http://sqlfiddle.com/#!3/92eac/2
Try this:
SELECT a.*
FROM b
CROSS APPLY
(
SELECT TOP (b.number) a.*
FROM a
WHERE a.link_id = b.link_id
ORDER BY
NEWID()
) a
Also see: SQLFiddle

Resources