IN NOT IN SQL Server 2005 - sql-server

How can I see what is not in the table... I know I know...can only see what is there but come on!!!
So!!
select * from ORDER where State IN ('MA','PA','GA','NC')
So I will get MA and PA but I want to see GA and NC....
NOT IN will return NY,NJ,CT ect.... I just want to see what is in the ( )

It looks like you are missing a single quote ' in front of GA.

My understanding of the question is: For a given list of states, which ones do not exist in the Order table?
This will show you what states out of the four listed below have no corresponding records in the Order table:
select distinct s.State
from
(
select 'MA' as State
union all
select 'PA'
union all
select 'GA'
union all
select 'NC'
) s
left outer join [Order] o on s.State = o.State
where o.State is null

I'm going to try to read between the lines a little here:
;with cteStates as (
select 'MA' as state
union all
select 'PA'
union all
select 'GA'
union all
select 'NC'
)
select s.state, count(o.state) as OrderCount
from cteStates s
left join [order] o
on s.state = o.state
group by s.state

Are you just trying to find out which states there are except for those four? If so:
SELECT DISTINCT State FROM dbo.ORDER WHERE State NOT IN ('MA', 'PA', 'GA', 'NC')

Related

UNION & ORDER two tables inside Common Table Expression

I have a CTE inside a SQL Stored Procedure that is UNIONing values from two databases - the values are customer numbers and that customer's last order date.
Here is the original SQL -
;WITH CTE_last_order_date AS
(
SELECT c1.customer ,MAX(s2.dt_created) AS last_order_date
FROM customers c1 WITH (NOLOCK)
LEFT JOIN archive_orders s2 WITH (NOLOCK)
ON c1.customer = s2.customer
GROUP BY c1.customer
UNION ALL
SELECT c1.customer ,MAX(s1.dt_created) AS last_order_date
FROM customers c1 WITH (NOLOCK)
LEFT JOIN orders s1 WITH (NOLOCK)
ON c1.customer = s1.customer
GROUP BY c1.customer
)
Example Results:
customer, last_order_date
CF122595, 2011-11-15 15:30:22.000
CF122595, 2016-08-15 10:01:51.230
(2 row(s) affected)
This obviously doesn't apply the UNION distinct records rule because the date values are not matched, meaning SQL returned the max value from both tables (i.e. the final record set was not distinct)
To try and get around this, I tried another method borrowed from this question and implemented grouping:
;WITH CTE_last_order_date AS
(
SELECT max(last_order_date) as 'last_order_date', customer
FROM (
SELECT distinct cust.customer, max(s2.dt_created) AS last_order_date, '2' AS 'group'
FROM customers c1 WITH (NOLOCK)
LEFT JOIN archive_orders s2 WITH (NOLOCK)
ON c1.customer = s2.customer
GROUP BY c1.customer
UNION
SELECT distinct c1.customer, max(sord.dt_created) AS last_order_date, '1' AS 'group'
FROM customers c1 WITH (NOLOCK)
LEFT JOIN orders s1 WITH (NOLOCK)
ON cust.customer = sord.customer
GROUP BY
c1.customer
) AS t
GROUP BY customer
ORDER BY MIN('group'), customer
)
Example Results:
customer, last_order_date
CF122595, 2016-08-15 10:01:51.230
(1 row(s) affected)
This had the distinction (hah) of working fine, up until clattering into the rule that prevents ORDER BY inside Common Table Expressions, which is needed in order to pick the lowest group (which would imply Live orders (group 1), whose date needs to take precedence over the Archive (group 2)).
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
All help or ideas appreciated.
Rather than grouping, then unioning, then grouping again, why not union the orders tables and work from there:
SELECT c1.customer ,MAX(s2.dt_created) AS last_order_date
FROM customers c1
INNER JOIN (select customer, dt_created from archive_orders
union all select customer, dt_created from orders) s2
ON c1.customer = s2.customer
GROUP BY c1.customer
Remember, in SQL your job is to tell the system what you want, not what steps/procedure to follow to get those results. The above, logically, describes what we're wanting - we want the last order date from each customer's orders, and we don't care whether that was an archived order or a non-archived one.
Since we're going to reduce the order information down to a single row (per customer) during the GROUP BY behaviour anyway, we don't also need the UNION to remove duplicates so I've switched to UNION ALL.
(I confess, I couldn't really see what the ORDER BY was supposed to be adding to the mix at this point so I've not tried to include it here. If this is going into a CTE, then reflect on the fact that CTEs, just like tables and views, have no inherent order. The only ORDER BY clause that affects the ordering of result rows is the one applied to the outermost/final SELECT)
Giving orders precedence over archived_orders:
;With CTE1 as (
SELECT c1.customer,group,MAX(s2.dt_created) as MaxInGroup
FROM customers c1
INNER JOIN (select customer, dt_created,2 as group from archive_orders
union all select customer, dt_created,1 from orders) s2
ON c1.customer = s2.customer
GROUP BY c1.customer,group
), CTE2 as (
SELECT *,ROW_NUMBER() OVER (PARTITION BY customer ORDER BY group) as rn
from CTE2
)
select * from CTE2 where rn = 1
An alternative approach could be to only get the customer from the archive table where we do not have a current one. Something like:
WITH CurrentLastOrders(customer, last_order_date) AS -- Get current last orders
(
SELECT o.customer, max(o.dt_created) AS last_order_date
FROM orders s WITH (NOLOCK) ON c.customer = o.customer
GROUP BY o.customer
),
ArchiveLastOrders(customer, last_order_date) AS -- Get archived last orders where customer does not have a current order
(
SELECT o.customer, max(o.dt_created) AS last_order_date
FROM archive_orders o WITH (NOLOCK)
WHERE NOT EXISTS ( SELECT *
FROM CurrentLastOrders lo
WHERE o.customer = lo.customer)
GROUP BY o.customer
),
AllLastOrders(customer, last_order_date) AS -- All customers with orders
(
SELECT customer, last_order_date
FROM CurrentLastOrders
UNION ALL
SELECT customer, last_order_date
FROM ArchiveLastOrders
)
AllLastOrdersPlusCustomersWithNoOrders(customer, last_order_date) AS -- All customerswith latest order if they have one
(
SELECT customer, last_order_date
FROM AllLastOrders
UNION ALL
SELECT customer, null
FROM customers c WITH (NOLOCK)
WHERE NOT EXISTS ( SELECT *
FROM AllLastOrders lo
WHERE c.customer = lo.customer)
)
I wouldn't try to nest SQL to achive a distinct result set, it's the same logic of grouping by customer in both unioned queries.
If you want a distinct ordered set, you can do that outside of the CTE
How about:
;WITH CTE_last_order_date AS
(
SELECT c1.customer ,s2.dt_created AS last_order_date, '2' AS 'group'
FROM customers c1 WITH (NOLOCK)
LEFT JOIN archive_orders s2 WITH (NOLOCK) ON c1.customer = s2.customer
UNION ALL
SELECT c1.customer ,s1.dt_created AS last_order_date, '1' AS 'group'
FROM customers c1 WITH (NOLOCK)
LEFT JOIN orders s1 WITH (NOLOCK) ON c1.customer = s1.customer
)
SELECT customer, MAX(last_order_date)
FROM CTE_last_order_date
GROUP BY customer
ORDER BY MIN('group'), customer
if you union all possible rows together, then calculate a row_number, partitioned on customer and ordered on 'group' then last_order_date descending, you can then select all the row=1 to give the 'top 1' per customer
;WITH CTE_last_order_date AS
(
SELECT max(last_order_date) as 'last_order_date', customer
FROM (
SELECT distinct cust.customer, max(s2.dt_created) AS last_order_date, '2' AS 'group'
FROM customers c1 WITH (NOLOCK)
LEFT JOIN archive_orders s2 WITH (NOLOCK)
ON c1.customer = s2.customer
GROUP BY c1.customer
UNION
SELECT distinct c1.customer, max(sord.dt_created) AS last_order_date, '1' AS 'group'
FROM customers c1 WITH (NOLOCK)
LEFT JOIN orders s1 WITH (NOLOCK)
ON cust.customer = sord.customer
GROUP BY
c1.customer
) AS t
GROUP BY customer
)
, --row_number below is 'per customer' and can be used to make rn=1 the top 1 for each customerid
ROWN AS (SELECT Customer,last_order_date,[group], row_number() OVER(partition by customer order by [group] ASC, sord.dt_created DESC) AS RN)
SELECT * FROM Rown WHERE Rown.rn = 1

Transforming and repeating multiple rows

I have a table that has two IDs within it named FamilyID and PersonID. I need to be able to repeat these rows with all combinations, as the below screenshot shows noting that each of the numbers get an extra row.
Here is some SQL to create the table with some sample data. There is no set number of occurrences that could occur.
Anyone aware of how we could be achieved?
CREATE TABLE #TempStackOverflow
(
FamilyID int,
PersonID int
)
insert into #TempStackOverflow
(
FamilyID,
PersonID
)
select
1012,
1
union
select
1013,
1
union
select
1014,
1
union
select
1015,
2
union
select
14774,
3
union
select
1019,
5
I understand that you need some sort of a complete list of matches within groups, but honestly, it would be much better if you would explain the business context, using plain English, in the first place.
The following query seems to produce your sample result:
with cte as (
select a.FamilyID, a.PersonID, a.PersonID as [GroupId] from #TempStackOverflow a
union all
select b.PersonID, b.FamilyID, b.PersonID from #TempStackOverflow b
)
select distinct c.FamilyID, s.PersonID
from cte c
inner join cte s on s.GroupId = c.GroupId
where c.FamilyID != s.PersonID;
Here is the simplest version I can come up with that groups the items by PersonId, as you do above. Obviously if you don't want that, then you can remove the outer query.
SELECT FamilyId,
PersonID
FROM (
SELECT FamilyId, PersonId, PersonID as SortBy
FROM #TempStackOverflow t1
UNION
SELECT PersonId, FamilyId, PersonId as SortBy
FROM #TempStackOverflow t1
UNION
SELECT t1.FamilyID, t2.FamilyID, t1.PersonID as SortBy
FROM #TempStackOverflow t1
FULL OUTER JOIN #TempStackOverflow t2
ON t1.PersonID = t2.PersonID
WHERE t1.FamilyID != t2.FamilyID
) as Src
ORDER BY SortBy

Distinct columns after "ORDER BY" in SQL server 2014

I want to distinct columns after ORDER BY points.pPoint.
this is points table diagram:
I want something as following image on the right side but getting result as the left side:
and this is my code:
SELECT TOP(6) MedicalExpertise.meid
FROM physician INNER JOIN
MedicalExpertise ON physician.meid = MedicalExpertise.meid INNER JOIN
points ON physician.phId = points.phID
ORDER BY points.pPoint DESC
Perhaps something like this?
SELECT DISTINCT meid
FROM ( SELECT TOP ( 6 ) MedicalExpertise.meid
FROM physician
INNER JOIN MedicalExpertise ON physician.meid = MedicalExpertise.meid
INNER JOIN points ON physician.phId = points.phID
ORDER BY points.pPoint DESC ) d
ORDER BY 1 DESC;
Simply use distinct keyword,
Ex:
SELECT DISTINCT column1, column2, ...
FROM table_name;
Can you edit the original question what you really want? Does it have to be grouped by any column before getting distinct? Please update the question.

SQL Server 2014 UNION in CROSS APPLY

I have the following query
SELECT DISTINCT
d.UserName,
i.itemID,
d.Score,
d.StoreCode,
d.Location
FROM
G.dbo.Users d
LEFT JOIN
G.dbo.Emails s on d.UserName=s.UserName
CROSS APPLY
(
SELECT TOP (1)
ii.ItemID
FROM
G.dbo.Dump ii
WHERE
ii.Username=d.UserName
AND
ii.endTime>DATEADD(hh,3,getDate())
) i
WHERE
s.serName is null
AND
d.Score>#_Score
AND
(d.processed=0)
GROUP BY
d.UserName,
i.itemID,
d.Score,
d.StoreCode,
d.Location
ORDER BY
d.UserName ASC
Now I need to modify it since Table G.dbo.Dump has been splitted into 20 smaller tables and now I have Dump_00 to Dump_19
I try to modify part of the CROSS APPLY section using UNION in this way
CROSS APPLY
(
SELECT TOP (1)
ii.ItemID
FROM
(
SELECT TOP (1) FROM G.dbo.Dump_00
UNION
SELECT TOP (1) FROM G.dbo.Dump_01
UNION
.....
SELECT TOP (1) FROM G.dbo.Dump_19
) ii
WHERE
ii.UserName=d.UserName
AND
ii.EndTime>DATEADD(hh,3,getDate())
) i
but result is not working as expected
can suggest if UNION is the right way and in case how to apply, or another solution?
Thanks!
Remove the TOP 1 from the union elements. Not sure why that was added. Logically, you are after a set that is the union of all tables.
Also, I don't think you want a union at all. You want the concatenation.
CROSS APPLY
(
SELECT TOP (1) ii.ItemID
FROM
(
SELECT FROM G.dbo.Dump_00 --changed
UNION ALL --changed
SELECT FROM G.dbo.Dump_01 --changed
.....
) ii
) i

Selecting Count from multiple tables and returning them all in one row - SQL Server

so the issue I'm trying to solve is I have 8 tables with data in them. And a 9th table, with a field for each table, that I want to store the count of each of the previous 8 tables. I'm able to return the counts however instead of one count per field, I have 8 rows just populating the first field. Each of the 8 table names is a field name in the 9th table. Here's my code:
SELECT COUNT(SubID) as Sent_Members FROM Sent_Members
UNION ALL
SELECT COUNT(SubID) as Sent_Shoppers FROM Sent_Shoppers
UNION ALL
SELECT COUNT(SubID) as Open_Members FROM Open_Members
UNION ALL
SELECT COUNT(SubID) as Open_Shoppers FROM Open_Shoppers
UNION ALL
SELECT COUNT(SubID) as Click_Members FROM Click_Members
UNION ALL
SELECT COUNT(SubID) as Click_Shoppers FROM Click_Shoppers
UNION ALL
SELECT COUNT(SubID) as Unique_Click_Members FROM Unique_Click_Members
UNION ALL
SELECT COUNT(SubID) as Unique_Click_Shoppers FROM Unique_Click_Shoppers
I'm guessing I should be using something instead of Union, but I'm not sure what that would be.. Thanks!
This looks uglier but it is hundreds of times more efficient than doing 8 subqueries with a complete table scan in each one.
;WITH r AS
(
SELECT t.name, rc = SUM(p.rows)
FROM sys.tables AS t
INNER JOIN sys.partitions AS p
ON t.[object_id] = p.[object_id]
WHERE p.index_id IN (0,1)
AND t.name IN
(
N'Sent_Members',
N'Sent_Shoppers',
N'Open_Members',
N'Open_Shoppers',
N'Click_Members',
N'Click_Shoppers',
N'Unique_Click_Members',
N'Unique_Click_Shoppers'
)
GROUP BY t.name
)
SELECT * FROM r
PIVOT (MAX(rc) FOR name IN
(
[Sent_Members],
[Sent_Shoppers],
[Open_Members],
[Open_Shoppers],
[Click_Members],
[Click_Shoppers],
[Unique_Click_Members],
[Unique_Click_Shoppers]
) AS p;
Here you go:
INSERT INTO [Table9]
SELECT
(SELECT COUNT(*) FROM Sent_Members) AS Sent_Members,
(SELECT COUNT(*) FROM Sent_Shoppers) AS Sent_Shoppers,
(SELECT COUNT(*) FROM Open_Members) AS Open_Members,
(SELECT COUNT(*) FROM Open_Shoppers) AS Open_Shoppers,
(SELECT COUNT(*) FROM Click_Members) AS Click_Members,
(SELECT COUNT(*) FROM Click_Shoppers) AS Click_Shoppers,
(SELECT COUNT(*) FROM Unique_Click_Members) AS Unique_Click_Members,
(SELECT COUNT(*) FROM Unique_Click_Shoppers) AS Unique_Click_Shoppers

Resources