TSQL display field values for column with count column in condition - sql-server

I have query which will group column 1 and 2 and calculate count for column3
(select col1, col2, count(col3)
from table1
group by col1,col2
Having count(col3) < 50)
But I want to display all fields values for col3 where count(col3) < 50 . Can you help me with this? Thank you

Try this:
select col1, col2, col3, t.cnt
from (
select col1, col2, col3,
count(col3) over (partition by col1, col2) AS cnt
from table1 ) as t
where t.cnt < 50
The idea is to use windowed version of COUNT instead of GROUP BY. COUNT(col3) OVER (PARTITION BY col1, col2) returns the count of col3 occurrences per col1, col2 for every row of table1. You can filter out col1, col2 slices having a count of 50 or more in an outer query.

You can also use something like this:
select t.col1, t.col2, t.col3
from table1 t
where
EXITS(select 1 from table1 t1 where t.col1 = t1.col1 and t.col2 = t.col2 having count(t1.col3) > 50)
or something like this:
select t.col1, t.col2, t.col3
from table1 t
inner join (select t1.col1, t1.col2, count(t1.col3) from table1 t1
group by t1.col1, t1.col2 having count(t1.col3) > 50) x
on t.col1 = x.col1 and t.col2 = x.col2

Related

Deactivate duplicate data based on two group by columns with check not null

I have this following query to return duplicate rows by 2 columns but it returns rows with NULL values. I would like to return rows with NOT NULL for both columns. Also how can I deactivate duplicate record with old ID?
With deactivaterows as (
Select t.*, count(*) over (partition by col1, col2) as cnt from TABLE1 t)
Select * from deactivaterows where cnt > 1;
You want row_number not count(*):
with deactivaterows as
(
select t.*, row_number() over(partition by t.col1, t.col2 order by (select null)) as rn
from TABLE1
where t.col1 is not null and t.col2 is not null
)
select * from deactivaterows where rn > 1
I would do it this way:
select col1, col2, count(*)
from TABLE1
where col1 is not null and col2 is not null
group by col1, col2
having count(*) > 1
The having command is great, it filters results after the group by and the select. You can always throw in a where regardless, and this will compare before you start grouping, counting or selecting anything.
Alternatively, you can certainly modify your existing solution by throwing in a where clause without issue:
With deactivaterows as (
Select t.*, count(*) over (partition by col1, col2) as cnt from TABLE1 t
where col1 is not null and col2 is not null)
Select * from deactivaterows where cnt > 1;

Insert 2 rows when a condition verified

I have a SELECT INTO #tTable SELECT CASE WHEN condition THEN value1 ELSE value2 query.
When a particular condition is verified I have to insert into #tTable 2 rows instead of 1 that differ each other only for 1 column.
I resolved this problem in this way:
Insert into #tTable a foo row with value for my column v1v2
Insert into #tTable value1 where col = v1v2
Insert into #tTable value2 where col = v1v2
Delete from #tTable where col = v1v2
Is there a better and more performance way to do this? Is there a way to insert 2 rows in an INSERT INTO #table SELECT CASE WHEN statement?
Example:
INSERT INTO #tTable (col1, col2, col3)
SELECT T.col1, T.col2, CASE WHEN T.col1 > T.col2 THEN v1v2
WHEN T.col1 = T.col2 THEN value1 ELSE value2 END
FROM Table1 as T;
INSERT INTO #tTable (col1, col2, col3)
SELECT T.col1, T.col2, value1
FROM Table1 as T
WHERE T.col3 = v1v2;
INSERT INTO #tTable (col1, col2, col3)
SELECT T.col1, T.col2, value2
FROM Table1 as T
WHERE T.col3 = v1v2;
DELETE FROM #tTable
WHERE col3 = v1v2;
I have to insert 2 rows (one with value1 and other with value2) on case when T.col1 > T.col2
EDIT:
Actually, my query is like this:
INSERT INTO #tTable (col1, col2, col3)
SELECT T.col1, T.col2,
CASE WHEN condition1 AND condition2 AND condition3 THEN value1
WHEN condition4 AND condition5 AND condition6 THEN value2
WHEN condition7 AND condition8 AND condition9 THEN v1v2 END
FROM Table1 as T
You can't generate another row with a CASE, you will have to use UNION ALL or an additional INSERT. The simplest way I see it is with a UNION ALL, repeating the condition for v1 + v2 on each SELECT:
INSERT INTO #tTable (
col1,
col2,
col3)
SELECT
V.Col1,
V.Col2,
col3 = V.value1
FROM
Table1 AS V
WHERE
(condition1 AND condition2 AND condition3) OR -- value1 condition
(condition7 AND condition8 AND condition9) -- shared condition
UNION ALL
SELECT
V.Col1,
V.Col2,
col3 = V.value2
FROM
Table1 AS V
WHERE
(condition4 AND condition5 AND condition6) OR -- value2 condition
(condition7 AND condition8 AND condition9) -- shared condition
If your conditions are bound to change or are complex, you can write them only once if you place them on a CTE and reference their output:
;WITH DataWithConditions AS
(
SELECT
T.Col1,
T.Col2,
T.Value1,
T.Value2,
Condition = CASE
WHEN condition1 AND condition2 AND condition3 THEN 1
WHEN condition4 AND condition5 AND condition6 THEN 2
WHEN condition7 AND condition8 AND condition9 THEN 3 END
FROM
Table1 AS T
)
INSERT INTO #tTable (
col1,
col2,
col3)
SELECT
V.Col1,
V.Col2,
col3 = V.value1
FROM
DataWithConditions AS V
WHERE
V.Condition IN (1, 3)
UNION ALL
SELECT
V.Col1,
V.Col2,
col3 = V.value2
FROM
DataWithConditions AS V
WHERE
V.Condition IN (2, 3)
You can try UNION ALL to incorporate the second column's value as ROW as shown below-
INSERT INTO #tTable (col1, col2, col3)
SELECT T.col1, T.col2,
CASE
WHEN T.col1 > T.col2 THEN value1 -- Column name may be v1v2
WHEN T.col1 = T.col2 THEN value1
ELSE value2
END
FROM Table1 AS T
UNION ALL
SELECT T.col1, T.col2,value2 -- Value2 I guess the 2nd column
FROM Table1 AS T WHERE T.col1 > T.col2

INSERT INTO multiple rows with subquery

I want to INSERT INTO by more than one value at a time, I did this by doing the following:
INSERT INTO table_1(col_1,col_2,col_3)
SELECT col_1, col2, (SELECT col3 FROM table_3)
FROM table_2
But col3 from table_3 is a datetime format, while col3 from table_1 needs an integer value. I did this by doing the following:
CAST(CONVERT(varchar(10),(SELECT col3 FROM table_3),112)AS int)
When I run this I get a more than one result in a subquery error. I have really no idea whatsoever on how to fix this. Hopefully you do.
Thank you in advance.
INSERT INTO table_1(col_1,col_2,col_3)
SELECT col_1, col2, (CAST(CONVERT(varchar(10),(SELECT top 1 col3 FROM table_3),112)AS int))
FROM table_2
You need to use top 1 to select 1 row
Well, I think the error says it all. You have to limit the inner query somehow with WHERE condition, with TOP or with MAX(col3) for example. Depends WHICH col3 you want.
You need to join table_2 to table_3. Not sure what your database structure is, but it should be something like this:
INSERT INTO table_1(col_1,col_2,col_3)
SELECT t2.col_1, t2.col2, t3.col3
FROM table_2 t2
INNER JOIN table_3 t3 on t3.t2id = t2.id
The alternative is to use TOP 1, to just return 1 record in the sub-query - but I would not recommend this as it may not be the value you want:
INSERT INTO table_1(col_1,col_2,col_3)
SELECT col_1, col2, (SELECT top 1 col3 FROM table_3)
FROM table_2
You can use CTE to prepare your data :
;WITH MyData (col1, col2, col3)
AS
(
SELECT col_1, col2, CAST(CONVERT(varchar(10),(col3),112)AS int)
FROM table_2 JOIN table_3 ON <join condition>
)
INSERT INTO table_1(col_1,col_2,col_3)
SELECT col_1, col2, col3
FROM MyData
Pls try below query :
INSERT INTO table_1(col_1,col_2,col_3)
SELECT col_1, col2, isnull((SELECT TOP 1 cast(col3 as int) FROM table_3),0)
FROM table_2

Is there a T-SQL shortcut for getting the max values of two columns

What I mean is, say you have a table like:
Col1 Col2
---- ----
1 1
1 9
2 1
2 3
4 1
4 2
I want to get: Col1=4 and Col2=2, because Col1 has precendence. In other words, I want the largest value of Col1 and for that value the largest value of Col2 in a minimal T-SQL expression. It's almost like saying:
SELECT TOP 1 Col1, Col2
FROM MyTable
ORDER BY Col1, Col2 DESC
But doing this in such a way that the Col1, Col2 values are usable within another query.
Not really anything like MAX(Col1, Col2). If you wanted to simulate MAX ... GROUP BY X you could use
WITH T AS
(
SELECT Col1,
Col2,
ROW_NUMBER () OVER (PARTITION BY X ORDER BY Col1 DESC, Col2 DESC) AS RN
FROM MyTable
)
SELECT Col1,
Col2,
X
FROM T
WHERE RN= 1;
Like this? One row
SELECT ...
FROM
SOmeTable
JOIN
(
SELECT TOP 1 Col1, Col2
FROM MyTable
ORDER BY Col1, Col2 DESC
) foo ON S.Col1 = foo.Col1
Or per outer row?
SELECT ...
FROM
SOmeTable S
CROSS APPLY
(
SELECT TOP 1 Col2
FROM MyTable M
WHERE S.somecol = M.SomeCol
ORDER BY Col2 DESC
) foo
SELECT ...
FROM
SOmeTable S
CROSS APPLY
(
SELECT Col1, MAX(Col2) AS MaxCOl2
FROM MyTable M
GROUP BY Col1
) foo ON S.Col1 = foo.Col1
WITH t(Col1,maxCol1,maxCol2) AS (
SELECT
Col1,
MAX(Col1) OVER(),
MAX(Col2) OVER(PARTITION BY Col1)
)
SELECT TOP 1 maxCo11,maxCol2 FROM t WHERE Col1 = maxCol1

Condition on two fields

I have a SQL Select and I am not sure how I can achieve this. I am checking two fields to see if any of those fields are in a list. So like,
Select * from MyTable where col1 or col2 in (select col3 from OtherTable where ID=1)
I tried
Select * from MyTable where
col1 in (select col3 from OtherTable where ID=1)
or col2 in (select col3 from OtherTable where ID=1)
But, this returns the records that match first condition (only returns col1, but not col2) for some reasons.
Try this -
Select * from MyTable where
(col1 in (select col3 from OtherTable where ID=1))
or
(col2 in (select col3 from OtherTable where ID=1) )
if you're subquery is the same for both columns, i'd throw it into a cte, then do a left outer join on the cte on col1 and col2, then do your where statement.
;with c3 as
(
select col3
from OtherTable
where ID=1
)
select m.*
from MyTable m
left outer join c3 as c1
on m.col1=c1.col3
left outer join c3 as c2
on m.col2=c2.col3
where
(c1.col3>'')
or (c2.col3>'')
if a blank varchar that isn't null is a viable option, change your where clauses to >=.
SELECT t.*
FROM MyTable t
INNER JOIN (
select col3
from OtherTable
where ID=1
) sel ON sel.col3 IN (t.col1, t.col2)

Resources