SQL Server | Finding out count and category - sql-server

Table A
Owner row_no category
-------------------------
A 1 U
B 1 T
B 2 T
C 1 U
C 2 T
C 3 U
C 4 U
I'm looking for a solution that stores values into other table which should retrieve
row_no as 1 if the value is 1 and should return max(row_no)-1 if the value isn't 1.
category should be either T or U or both based on whether an owner has opted for only T or U or both in TABLE A.
Expected table output should be something like below.
Owner row_no category
---------------------------
A 1 U
B 1 T
C 3 Both
I tried using the below approach which turns out to be an error.
SELECT *
INTO B
FROM A
WHERE ROW_NO LIKE CASE
WHEN ROW_NO = 1 THEN ROW_NO
ELSE MAX(ROW_NO) - 1
END
Haven't figured out yet on retrieving the category!
Could you please help with correct approach?

Your logic is not completely clear to me. In particular, I assume here that your logic for reporting the row_no is to return 1 when the max value for an owner is 1, otherwise to return that max value minus 1.
We can try doing a simple aggregation query here to generate what you want.
SELECT
Owner,
CASE WHEN MAX(row_no) = 1 THEN 1 ELSE MAX(row_no) - 1 END AS row_no,
CASE WHEN COUNT(DISTINCT category) > 1 THEN 'Both' ELSE MAX(category) END AS category
FROM tableA
GROUP BY
Owner;
Demo

One method would be to use a GROUP BY:
WITH VTE AS(
SELECT *
FROM(VALUES ('A',1,'U'),
('B',1,'T'),
('B',2,'T'),
('C',1,'U'),
('C',2,'T'),
('C',3,'U'),
('C',4,'U')) V([Owner], Row_no, Category))
SELECT [Owner],
ISNULL(NULLIF(MAX(Row_no) - 1,0),1) AS Row_no,
CASE WHEN MIN(Category) = MAX(Category) THEN MAX(Category) ELSE 'Both' END AS Category --Assumes Category cannot have a value of NULL
FROM VTE
GROUP BY [Owner];

Related

Is there a way to Merge SQL Server Row Query?

Please look at my current summary query result :
id name mch
127664 ML 2
127666 ML 2
127667 ML 2
127670 ML 2
127671 ML 2
127672 ML 2
127674 ML 2
127675 ML 2
127678 ML 1
127680 ML 1
127665 ML 2
I want to merge row which has same value..
Just merge the name column.
And then here is my expected query :
id name mch
127664 ML 2
127666 2
127667 2
127670 2
127671 2
127672 2
127674 2
127675 2
127678 1
127680 1
127665 2
I already look for some problem but still not found.
I hope you want to guide me to handle this..
Well you could try a ROW_NUMBER trick here:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id) rn
FROM yourTable
)
SELECT
id,
CASE WHEN rn = 1 THEN name ELSE '' END AS name,
mch
FROM cte
ORDER BY
name,
id;
But typically this type of requirement would be better handled in your presentation layer (e.g. PHP or Java).
Your query should be like this :
WITH t AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id) counter
FROM table //nameofyourtable
)
SELECT
id,CASE WHEN counter = 1 THEN name ELSE '' END AS name, mch
FROM t ORDER BY
name,
id;

Find dup records with different extensions in SQL Server

I have a subscriptions table. Sample records:
SUBS_ID | SUBS Name
1 | SC FORM 124
2 | SC FORM 124-R
I need to find both the records, as the subscription name is exactly the same but just with an extension-R.
Really bad throwaway code written straight here and untested, but...
with cte As (Select Name, Id
From Subs
Where Name Not Like '%-R'
)
Select cte.Id, cte.Name, M.Name
From Subs As M
Join cte
On cte.Name + '-R' = M.Name
You can use row_Number and partition by as below:
Select * from (
Select *, DupeRecords = Row_number() over(partition by replace([Subs Name],'-R','') order by Subs_Id)
from #yoursubs
) a Where a.DupeRecords > 1
Based on your latest criteria:
So, in the above example when I query the table I should get all 3
records ...the first one being the base record and the remaining 2
being the extensions – SQL User 17 mins ago
SELECT distinct
0 as Subs_ID
, CASE WHEN SUBS_Name like '%-%' THEN left(SUBS_Name,charindex('-',SUBS_Name)-1) ELSE SUBS_Name END AS SUB_NAME_MAIN
, '' as Extension
FROM
subs
UNION
SELECT
Subs_ID
, CASE WHEN SUBS_Name like '%-%' THEN left(SUBS_Name,charindex('-',SUBS_Name)-1) ELSE SUBS_Name END AS SUB_NAME_MAIN
, CASE WHEN SUBS_Name like '%-%' THEN RIGHT(SUBS_Name, LEN(SUBS_Name) - charindex('-',SUBS_Name)+1) ELSE '' END AS Extension
FROM
subs
will produce the following result. A 'Master' row that is given an arbitray ID number of '0' and each row of that master's family and its extension.
Subs_ID SUB_NAME_MAIN Extension
----------- -------------------- --------------------
0 SC FORM 124
1 SC FORM 124
2 SC FORM 124 -R

SQL GROUP BY with columns which contain mirrored values

Sorry for the bad title. I couldn't think of a better way to describe my issue.
I have the following table:
Category | A | B
A | 1 | 2
A | 2 | 1
B | 3 | 4
B | 4 | 3
I would like to group the data by Category, return only 1 line per category, but provide both values of columns A and B.
So the result should look like this:
category | resultA | resultB
A | 1 | 2
B | 4 | 3
How can this be achieved?
I tried this statement:
SELECT category, a, b
FROM table
GROUP BY category
but obviously, I get the following errors:
Column 'a' is invalid in the select list because it is not contained
in either an aggregate function or the GROUP BY clause.
Column 'b' is invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
How can I achieve the desired result?
Try this:
SELECT category, MIN(a) AS resultA, MAX(a) AS resultB
FROM table
GROUP BY category
If the values are mirrored then you can get both values using MIN, MAX applied on a single column like a.
Seams you don't really want to aggregate per category, but rather remove duplicate rows from your result (or rather rows that you consider duplicates).
You consider a pair (x,y) equal to the pair (y,x). To find duplicates, you can put the lower value in the first place and the greater in the second and then apply DISTINCT on the rows:
select distinct
category,
case when a < b then a else b end as attr1,
case when a < b then b else a end as attr2
from mytable;
Considering you want a random record from duplicates for each category.
Here is one trick using table valued constructor and Row_Number window function
;with cte as
(
SELECT *,
(SELECT Min(min_val) FROM (VALUES (a),(b))tc(min_val)) min_val,
(SELECT Max(max_val) FROM (VALUES (a),(b))tc(max_val)) max_val
FROM (VALUES ('A',1,2),
('A',2,1),
('B',3,4),
('B',4,3)) tc(Category, A, B)
)
select Category,A,B from
(
Select Row_Number()Over(Partition by category,max_val,max_val order by (select NULL)) as Rn,*
From cte
) A
Where Rn = 1

Use NOT Equal condition in sql?

I want to fetch orders that have a “Received” (ActivityID = 1) activity but not a “Delivered” (ActivityID = 4) activity on orders table. i.e orders that are received but not deliverd yet.
my query is
SELECT OrderID FROM tblOrderActivity
where (tblOrderActivity.ActivityID = 1 AND tblOrderActivity.ActivityID != 4)
GROUP BY OrderID
it is not returning desired result.
result should be orderID 2 and 4
Your query doesn't really make sense. Grouping happens after WHERE clause, so you're basically getting all orders that have ActivityID ==1 (because if activity Id is 1 there it's always not equal to 4).
After WHERE clause is applied you end up with following rows:
OrderID ActivityID
1 1
2 1
3 1
4 1
And these are the orders you group. No more condition is evaluated.
If 4 is the highest possible ActivityID you could do following:
SELECT OrderID
FROM tblOrderActivity
GROUP BY OrderID
HAVING MAX(ActivityID) < 4
HAVING condition is applied after grouping, which is what you want.
I don't think Group by is needed here. You can use a Subquery to find he order's which is not delivered. Try this.
SELECT *
FROM Yourtable a
WHERE a.ActivityID = 1
AND NOT EXISTS (SELECT 1
FROM yourtable b
WHERE a.OrderID = b.OrderID
AND b.ActivityID = 4)

Get the missing value in a sequence of numbers

I made the following query for the SQL Server backend
SELECT TOP(1) (v.rownum + 99)
FROM
(
SELECT incrementNo-99 as id, ROW_NUMBER() OVER (ORDER BY incrementNo) as rownum
FROM proposals
WHERE [year] = '12'
) as v
WHERE v.rownum <> v.id
ORDER BY v.rownum
to find the first unused proposal number.
(It's not about the lastrecord +1)
But I realized ROW_NUMBER is not supported in access.
I looked and I can't find something similar.
Does anyone know how to get the same result as a ROW_NUMBER in access?
Maybe there's a better way of doing this.
Actually people insert their proposal No (incrementID) with no constraint. This number looks like this 13-152. xx- is for the current year and the -xxx is the proposal number. The last 3 digits are supposed to be incremental but in some case maybe 10 times a year they have to skip some numbers. That's why I can't have the auto increment.
So I do this query so when they open the form, the default number is the first unused.
How it works:
Because the number starts at 100, I do -99 so it starts at 1.
Then I compare the row number with the id so it looks like this
ROW NUMBER | ID
1 1 (100)
2 2 (101)
3 3 (102)
4 5 (104)<--------- WRONG
5 6 (105)
So now I know that we skip 4. So I return (4 - 99) = 103
If there's a better way, I don't mind changing but I really like this query.
If there's really no other way and I can't simulate a row number in access, i will use the pass through query.
Thank you
From your question it appears that you are looking for a gap in a sequence of numbers, so:
SELECT b.akey, (
SELECT Top 1 akey
FROM table1 a
WHERE a.akey > b.akey) AS [next]
FROM table1 AS b
WHERE (
SELECT Top 1 akey
FROM table1 a
WHERE a.akey > b.akey) <> [b].[akey]+1
ORDER BY b.akey
Where table1 is the table and akey is the sequenced number.
SELECT T.Value, T.next -1 FROM (
SELECT b.Value , (
SELECT Top 1 Value
FROM tblSequence a
WHERE a.Value > b.Value) AS [next]
FROM tblSequence b
) T WHERE T.next <> T.Value +1

Resources