Which invoices are greater than $300, that have been paid prior to 7/15/2008 and are either TermsID 2 or 3 - sql

I got this far from my homework question, but I am little confused how the code will work for paid prior for date and termsID 2 or 3?
Write a SELECT statement that returns VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, TermsID and PaymentDate that answers the following question: Which invoices are greater than $300, that have been paid prior to 7/15/2008 and are either TermsID 2 or 3? (18 records will be returned)
Select VendorID, invoiceNumber, InvoiceDate, InvoiceTotal, TermsID, PaymentDate
From invoices
Where invoices > 300 and

Here are some pointers:
If your column for paid date is (as it should be) a date, you can structure a predicate that looks for things before a date using the < operator jsut as you would with a number. Later dates are greater:
--find all people born before 1970 jan 01
SELECT * FROM person WHERE birthdate < '1970-01-01'
Pass your date for comparison as a string (surrounded by ') in yyyy-MM-dd format. The db will convert the string to a date and run the comparison numerically
Use the IN operator when you want to look for a column being in a set of terms:
SELECT * FROM person WHERE jobrole IN ('manager', 'developer', 'support')
SELECT * FROM creature WHERE numberoflegs IN (2,4,6)
IN works like:
SELECT * FROM creature WHERE numberoflegs =2 OR numberoflegs = 4 OR numberoflegs = 6
Always, always include brackets when mixing AND and OR, to make it clear to the DB and to other people reading your code, what is to be combined in which way
--for this...
SELECT * FROM person WHERE name = 'john' and age = 32 or city = 'paris'
--which of these is it? very different things!
SELECT * FROM person WHERE (name = 'john' and age = 32) or city = 'paris'
SELECT * FROM person WHERE name = 'john' and (age = 32 or city = 'paris')

Related

Fix Join table functions or not duplicate values?

So I have a query in NaviCat, it has a part that looks like this:
case
when base.table = 1 then Table1.Name
when base.table = 2 then Table2.Name
when base.table = 3 then Table3.Name
when base.table = 4 then Table4.Name
end as Name
As the Base table has the Identifier Number, but does not contain the Names of the person. It is connected properly and works. However, It is tripling some rows in certain cases.
I can get a response back that looks similar to this
Identifier Amount Name
12 1000 Smith, Suzy
12 1000 Smith, John
12 1000 Smith, John & Smith, Suzy
I would like it to only return the longest entry (as all the Names are either Husband, Wife, or Husband & Wife), as all the amounts are the same and I think it is because I am left joining the Base table to the Table1, Table2, etc. But how can I fix this? Is there a function to only return the longest Name?
I am looking at a few left joins similar to this.
Left join server.table1 as Table1 on Base.Identifier = Table1.Identifier AND Base.Date = Table1.Date
each table1-table4 has the same join code.
I can only provide a "raw" SQL solution, as I never used NaviCat.
Below solution assumes that for every Identifier in any of table1-table4, the Amount and the Date values are the same.
Your FROM should be changed like this:
left join (
select Identifier, Amount, Date, MAX(LEN(Name)) as LongestName
from server.table1
group by Identifier, Amount, Date
UNION ALL
select Identifier, Amount, Date, MAX(LEN(Name)) as LongestName
from server.table2
group by Identifier, Amount, Date
UNION ALL
select Identifier, Amount, Date, MAX(LEN(Name)) as LongestName
from server.table3
group by Identifier, Amount, Date
UNION ALL
select Identifier, Amount, Date, MAX(LEN(Name)) as LongestName
from server.table4
group by Identifier, Amount, Date
) as tables1to4 on Base.Identifier = tables1to4.Identifier AND Base.Date = tables1to4.Date
and your case expression becomes only
tables1to4.LongestName as Name
and the same applies to Amount, if it is needed in the end result (no case necessary).

Query with multiple string with like operator

I am new to SQL and I have this question on a homework assignment: "List the ids of customer representatives whose id is under 100 along with the total number of customers that each of these representatives serves in zip codes starting with 9 or 0 (combined)"
SO far I have this code:
SELECT cust_rep, count(cust_nbr) as "CustomerCount"
FROM customer
WHERE cust_rep < 100
GROUP BY cust_rep
ORDER BY cust_rep;
But I do not know how to add in the zip code restriction. Thanks for your help!
This will do what your query is doing in addition to makeusre sure the first chararacter of the zipcode is either a 0 or a 9
SELECT cust_rep, count(cust_nbr) as "CustomerCount"
FROM customer
WHERE cust_rep < 100
AND (
// adding quotes to avoid implicit conversion
LEFT(ZipCode, 1) = '0'
OR LEFT(ZipCode, 1) = '9'
)
GROUP BY cust_rep
ORDER BY cust_rep;
Try this.
SELECT CUST_REP, COUNT(*) as "CustomerCount"
FROM CUSTOMER
WHERE cust_rep < 100
AND (zipCode like '0%' OR zipCode like '9%')
GROUP BY cust_rep
ORDER BY cust_rep;

MS Access SQL - Most Recent Record for Each Consultant ID

I have spent some time on StackOverflow looking for this answer and trying a bunch of these solutions without luck. I feel like I am missing something minor but I cannot resolve it. NOTE - Learning SQL and using Access because that is what work uses.
I have 2 tables, 1 has consultant information in it (Columns:Consultant ID, First Name, Last Name, Active (Yes or No Checkbox). The 2nd table has their Weekly Numbers (Columns: AutoGenID, Consultant ID, WeekOf (Date), FullService, Consulting, Classified, Reallocations, RecruitmentSrvs) and joined them on ConsultantID (primary key)
I built a simply query to Join the 2 tables and show all the results ONLY for the active consultants in qry_Join (anyone marked not active does not show in this query) qry_Join returns Consultant ID, First Name, & Last Name (From tbl_Consultants) and then WeekOf (Date), FullService, Consulting, Classified, Reallocations, RecruitmentSrvs from tbl_WeeklyNumbers.
Question:
I would like to have a query that shows ONLY the most recent WeekOf (Date)entry by each consultant.
Issue:
SQL I am using is below but the issue I am having is that if ConsultantID #'s 3, 4, 5, 6, & 7 use a 10/11/2017 date and then ConsultantID #8 uses a 10/12/2017, the query will only return ConsultantID #8's row since it is most recent. I need it to still return all the other consultants most recent rows as well even if they are a date prior to ConsultantID #8s'
SQL:
SELECT ConsultantID, FirstName, WeekOf, USFullService, USConsulting, Classified, Reallocations, RecruitmentSrvs
FROM qry_Join
Where WeekOf = (SELECT MAX(WeekOf) FROM qry_Join)
Just pass ConsultantID to your subquery:
SELECT ConsultantID, FirstName, WeekOf, USFullService, USConsulting, Classified, Reallocations, RecruitmentSrvs
FROM qry_Join q
Where WeekOf = (SELECT MAX(s.WeekOf) FROM qry_Join s WHERE s.ConsultantID = q.ConsultantID)
SELECT ConsultantID,
FirstName,
WeekOf,
USFullService,
USConsulting,
Classified,
Reallocations,
RecruitmentSrvs
FROM qry_Join INNER JOIN
(SELECT MAX(WeekOf) maxwkof ,ConsultantID cid
FROM qry_Join
GROUP BY ConsultantID )
ON ConsultantID = cid
WHERE maxwkof = WeekOf
The issue in your query is, The below query gives a max date in the whole table. And that max id Matches only one consultant. SO you get one row
WeekOf = (SELECT MAX(WeekOf) FROM qry_Join)
The below query will give the max date of each consultant. SO you can join the max date and Consultant ID to get the details for each consultant in their latest weekoff
SELECT MAX(WeekOf) maxwkof ,ConsultantID cid
FROM qry_Join
GROUP BY ConsultantID

how to perform multiple aggregations on a single SQL query

I have a table with Three columns:
GEOID, ParcelID, and PurchaseDate.
The PKs are GEOID and ParcelID which is formatted as such:
GEOID PARCELID PURCHASEDATE
12345 AB123 1/2/1932
12345 sfw123 2/5/2012
12345 fdf323 4/2/2015
12346 dfefej 2/31/2022 <-New GEOID
What I need is an aggregation based on GEOID.
I need to count the number of ParcelIDs from last month PER GEOID
and I need to provide a percentage of that GEOID of all total sold last month.
I need to produce three columns:
GEOID Nbr_Parcels_Sold Percent_of_total
For each GEOID, I need to know how many Parcels Sold Last month, and with that Number, find out how much percentage that entails for all Solds.
For example: if there was 20 Parcels Sold last month, and 4 of them were sold from GEOID 12345, then the output would be:
GEOID Nbr_Parcels_Sold Perc_Total
12345 4 .2 (or 20%)
I am having issues with the dual aggregation. The concern is that the table in question has over 8 million records.
if there is a SQL Warrior out here who have seen this issue before, Any wisdom would be greatly appreciated.
Thanks.
Hopefully you are using SQL Server 2005 or later version, in which case you can get advantage of windowed aggregation. In this case, windowed aggregation will allow you to get the total sale count alongside counts per GEOID and use the total in calculations. Basically, the following query returns just the counts:
SELECT
GEOID,
Nbr_Parcels_Sold = COUNT(*),
Total_Parcels_Sold = SUM(COUNT(*)) OVER ()
FROM
dbo.atable
GROUP BY
GEOID
;
The COUNT(*) call gives you counts per GEOID, according to the GROUP BY clause. Now, the SUM(...) OVER expression gives you the grand total count in the same row as the detail count. It is the empty OVER clause that tells the SUM function to add up the results of COUNT(*) across the entire result set. You can use that result in calculations just like the result of any other function (or any expression in general).
The above query simply returns the total value. As you actually want not the value itself but a percentage from it for each GEOID, you can just put the SUM(...) OVER call into an expression:
SELECT
GEOID,
Nbr_Parcels_Sold = COUNT(*),
Percent_of_total = COUNT(*) * 100 / SUM(COUNT(*)) OVER ()
FROM
dbo.atable
GROUP BY
GEOID
;
The above will give you integer percentages (truncated). If you want more precision or a different representation, remember to cast either the divisor or the dividend (optionally both) to a non-integer numeric type, since SQL Server always performs integral division when both operands are integers.
How about using sub-query to count the sum
WITH data AS
(
SELECT *
FROM [Table]
WHERE
YEAR(PURCHASEDATE) * 100 + MONTH(PURCHASEDATE) = 201505
)
SELECT
GEOID,
COUNT(*) AS Nbr_Parcels_Sold,
CONVERT(decimal(18,8), COUNT(*)) /
(SELECT COUNT(*) FROM data) AS Perc_Total
FROM
data t
GROUP BY
GEOID
EDIT
To update another table by the result, use UPDATE under WITH()
WITH data AS
(
SELECT *
FROM [Table]
WHERE
YEAR(PURCHASEDATE) * 100 + MONTH(PURCHASEDATE) = 201505
)
UPDATE target SET
Nbr_Parcels_Sold = source.Nbr_Parcels_Sold,
Perc_Total = source.Perc_Total
FROM
[AnotherTable] target
INNER JOIN
(
SELECT
GEOID,
COUNT(*) AS Nbr_Parcels_Sold,
CONVERT(decimal(18,8), COUNT(*)) /
(SELECT COUNT(*) FROM data) AS Perc_Total
FROM
data t
GROUP BY
GEOID
) source ON target.GEOID = source.GEOID
Try the following. It grabs the total sales into a variable then uses it in the subsequent query:
DECLARE #pMonthStartDate DATETIME
DECLARE #MonthEndDate DATETIME
DECLARE #TotalPurchaseCount INT
SET #pMonthStartDate = <EnterFirstDayOfAMonth>
SET #MonthEndDate = DATEADD(MONTH, 1, #pMonthStartDate)
SELECT
#TotalPurchaseCount = COUNT(*)
FROM
GEOIDs
WHERE
PurchaseDate BETWEEN #pMonthStartDate
AND #MonthEndDate
SELECT
GEOID,
COUNT(PARCELID) AS Nbr_Parcels_Sold,
CAST(COUNT(PARCELID) AS FLOAT) / CAST(#TotalPurchaseCount AS FLOAT) * 100.0 AS Perc_Total
FROM
GEOIDs
WHERE
ModifiedDate BETWEEN #pMonthStartDate
AND #MonthEndDate
GROUP BY
GEOID
I'm guessing your table name is GEOIDs. Change the value of #pMonthStartDate to suit yourself. If your PKs are as you say then this will be a quick query.

SQL Select Query With Count And Where Statement

I always seem to trip myself up during these types of SQL Statements. Here is what I'm attempting to accomplish.
My Example Table
Name Date Type
Bob 9/28/11 1
Bob 9/27/11 1
Bob 9/28/11 2
Debra 9/28/11 1
I'm trying to write a SQL Statement that would give me all the names, their total count occured, and then a Date Filter. I'll write a rought statement with completely wrong syntax, but I think it'll convey what I'm attempting to do...I think.
SELECT Name, Count(*) As Total
FROM Table
GROUP BY Name, Total
WHERE Date = Today (I'm aware you can't do a WHERE in a GROUP BY) AND Type = 1
Essentially, I would like to get back a set of data that would show the Name, how many instances of Type 1 for today.
I don't think I'm searching for the proper question to actually be able to effectively research this on my own as well, probably because I'm wording it improperly.
Any help would be appreciated!
Your WHERE was in the wrong place:
SELECT Name, Count(*) As Total
FROM Table
WHERE Date = Today AND Type = 1
GROUP BY Name
You just need to move your WHERE after your FROM.
SELECT Name, Count(*) As Total
FROM Table
WHERE [Date] = CAST(getdate() as Date) -- or 'Jan 1 1990'
AND [Type] = 1
GROUP BY Name
WHERE comes before GROUP
SELECT Name, Count(*) As Total
FROM Table
WHERE Date >= #Today --assuming your date passed in has no time
AND Date < DATEADD(d,1,#Today)
AND Type = 1
GROUP BY Name, Total
example you can run
SELECT LEFT(name,1) FROM sysobjects
WHERE name < 'p'
GROUP BY LEFT(name,1)