Test ALL rows exists - sql

It is very simple to test when row exists or not.
if exists(select * from dbo.APQP_head where zestaw=#zestaw)
I want to test in my query whether all rows satisfy the condition.
I need use some query like this
if All exists(select * from dbo.APQP_head where zestaw=#zestaw and type=3)
But this syntax is not correct.

if NOT exists(select * from dbo.APQP_head where zestaw<>#zestaw OR type<>3)
--all rows satisfy the condition
if your columns can be nullable, then
if NOT exists(select * from dbo.APQP_head where zestaw<>#zestaw OR type<>3)
AND NOT exists(select * from dbo.APQP_head where zestaw IS NULL OR type IS NULL)

This may perform better than an OR because it keep the AND and uses semi-joins
IF NOT EXISTS (
SELECT zestaw, [type] FROM #foo
EXCEPT
SELECT zestaw, [type] FROM #foo where zestaw=#zestaw and type=3
)
-- all rows etc
Edit, quick and dirty test (SQL Server 2008 R2 Express on workstation), the EXCEPT uses more IO (2 touches) but less CPU (more efficient plan)
If you replace #zestaw with a constant, the NOT EXISTS .. OR .. wins
CREATE TABLE excepttest (zestaw int, [type] int);
INSERT excepttest VALUES (1, 3);
GO
INSERT excepttest SELECT excepttest.* FROM excepttest
GO 21
SELECT COUNT(*) FROM excepttest
GO
CREATE INDEX IX_Test ON excepttest (zestaw, [type]);
GO
DECLARE #zestaw int = 1;
SET STATISTICS IO ON
SET STATISTICS TIME ON
if NOT exists(select * from excepttest where zestaw<>#zestaw OR [type]<>3)
SELECT 'all match'
ELSE
SELECT 'some match';
IF NOT EXISTS (
SELECT zestaw, [type] FROm excepttest
EXCEPT
SELECT zestaw, [type] FROm excepttest where zestaw=#zestaw and [type]=3
)
SELECT 'all match'
ELSE
SELECT 'some match';
SET STATISTICS IO OFF
SET STATISTICS TIME OFF
DROP TABLE excepttest

You can invert the conditions in the WHERE clause and the whole exists expression:
if NOT exists select(select * from dbo.APQP_head where zestaw <> #zestaw OR type <> 3)
This uses a well known fact that NOT(A1 AND A2 AND ... An) == NOT(A1) OR NOT(A2)... OR NOT(An).

if not exists(select * from dbo.APQP_head where not (zestaw=#zestaw and type=3))

this is a solution for some problems:
select distinct AccAccountId from AccAccountTafsilType where AccAccountId
in (select Id From AccountForSooratVaziatFunc(5))
and AccAccountId in (select AccAccountId from AccAccountTafsilType where
TafsilTypeId in (select Id from AccTafsilType where ComplexId = 5 and
Code = 115))
and AccAccountId in (select AccAccountId from AccAccountTafsilType where
TafsilTypeId in (select Id from AccTafsilType where ComplexId = 5 and
Code = 116))

Related

Collation Conflict can not solve in SQL server

This is my query:
SELECT
CASE WHEN (
select Count(*) From (
select * from [mslccard08].[carekey].dbo.EXTERNAL_MEMBER_DATA
union
select * from [vmslcsql11].[HSRTest].dbo.External_Member_data) as t
)
<>
(
Select count(*) From [mslccard08].[carekey].dbo.EXTERNAL_MEMBER_DATA
)
THEN 'Data is not Identical'
ELSE 'Date is identical'
END AS RowCountResult
I am getting Following error
cannot resolve the collation conflict between sql_latin1_general_cp1_ci_as and sql_latin1_general_cp1_ci_ai
I know that error is because collation mismatch for one of the my column external Data with nvarchar type
I can solve the error by using DefaultCollation. As much as I understood DefaultCollation is used only with column_name. I am using * here. I don't know how to solve this error with scenario
Please find below the solution for your problem.
Change the table names with your tables.
declare #count as int
set #count =
(Select Count(*) from
(select * from Broker
union
select * from Broker) as t)
SELECT
CASE WHEN
(
#count <> (select count(*) from Broker)
)
THEN 'Data is not Identical'
ELSE 'Date is identical'
END AS RowCountResult
Your issue is related to using select *. Always avoid using this.
You were trying to union two columns with different collations. You wouldn't know which ones though because you were using select *
The statement below doesn't use select * at all and is likely to be much faster as it should work out the count on the remote server and return only three rows in total. Also it does not use union which is an expensive operation.
The important question is: did you mean to use union instead of union all ?
SELECT
RowCount1,
RowCount2,
CASE WHEN RowCount1 <> RowCount2
THEN 'Data is not Identical'
ELSE 'Date is identical'
END AS RowCountResult
FROM
(
SELECT
(select Count(*) From mslccard08.[carekey].dbo.EXTERNAL_MEMBER_DATA)
+
(select Count(*) from [vmslcsql11].[HSRTest].dbo.External_Member_data)
As RowCount1,
(
Select count(*) From [mslccard08].[carekey].dbo.EXTERNAL_MEMBER_DATA
)
As RowCount2
) As SubTable
SELECT
CASE WHEN (
select Count(1) From (
select field1 COLLATE sql_latin1_general_cp1_ci_as field1, field2 COLLATE sql_latin1_general_cp1_ci_as field2 from [mslccard08].[carekey].dbo.EXTERNAL_MEMBER_DATA
union
select field1 COLLATE sql_latin1_general_cp1_ci_as field1, field2 COLLATE sql_latin1_general_cp1_ci_as field2 from [vmslcsql11].[HSRTest].dbo.External_Member_data
) t)
<>
(
Select count(*) From [mslccard08].[carekey].dbo.EXTERNAL_MEMBER_DATA
)
THEN 'Data is not Identical'
ELSE 'Date is identical'
END AS RowCountResult
You need to correct the field names, it should work in union.
Changing collation with * does not seem to be possible.
EDIT:Temp Table Option to change COLLATE when using * in select
Create a temp table for first statement of the union then upsert records from second statement of the union and use this temp table for getting both table's count, refer code example below.
create table t1(name varchar(10) COLLATE French_CI_AS);
create table t2(name varchar(10) COLLATE Latin1_General_CI_AS);
insert into t1 values ('`ffffn1');
insert into t2 values('general');
select * into #t from t1; -- First table of union
Insert into #t select * from t2; -- second table of union
select count(*) from #t; -- working
------------------------------------------
So your query will change to;
select * into #EXTERNAL_MEMBER_DATA from [mslccard08].[carekey].dbo.EXTERNAL_MEMBER_DATA ; -- Create temp table having carekey records
Insert into #EXTERNAL_MEMBER_DATA select * from [vmslcsql11].[HSRTest].dbo.External_Member_data; -- add records from HSRTest
-- Use the temp table in query
SELECT CASE WHEN (select Count(1) From #EXTERNAL_MEMBER_DATA )
<>
(Select count(*) From [mslccard08].[carekey].dbo.EXTERNAL_MEMBER_DATA)
THEN 'Data is not Identical'
ELSE 'Date is identical'
END AS RowCountResult

Using IF / ELSE to determine a SELECT INTO statement

I'm having some strange issues using IF / ELSE to determine which one or two SELECT statements to execute. The error message I'm getting when running the full statement is that my temporary table already exists, but that does not occur if I run two separate executions of two separate IF statements.
Here is the code in SQL Server:
IF (select BusinessDayCount from Calendartbl) <= 1
BEGIN
SELECT * into #temp1
FROM PreviousMonthTbl
END
ELSE
BEGIN
SELECT * into #temp1
FROM CurrentMonthTbl
END
It's a "feature" of the syntax checking in SQL Server. You simply cannot "create" a #temporary table twice within the same batch.
This is the pattern you need.
SELECT * into #temp1
FROM PreviousMonthTbl
WHERE 1=0;
IF (select BusinessDayCount from Calendartbl) <= 1
BEGIN
INSERT into #temp1 SELECT *
FROM PreviousMonthTbl
END
ELSE
BEGIN
INSERT into #temp1 SELECT *
FROM CurrentMonthTbl
END
If you prefer, you can also express the branch (in this case) as a WHERE clause:
SELECT * into #temp1
FROM PreviousMonthTbl
WHERE (select BusinessDayCount from Calendartbl) <= 1
UNION ALL
SELECT *
FROM CurrentMonthTbl
WHERE isnull((select BusinessDayCount from Calendartbl),2) > 1
You can't use SELECT INTO for a tables with same name in the same batch. Use a different name for a temporary table
IF EXISTS(
SELECT 1
FROM Calendartbl
WHERE BusinessDayCount <= 1
)
BEGIN
IF OBJECT_ID('tempdb.dbo.#PreviousMonthTbl') IS NULL DROP TABLE dbo.#PreviousMonthTbl
SELECT *
INTO #PreviousMonthTbl
FROM PreviousMonthTbl
END
ELSE
BEGIN
IF OBJECT_ID('tempdb.dbo.#CurrentMonthTbl') IS NULL DROP TABLE dbo.#CurrentMonthTbl
SELECT *
INTO #CurrentMonthTbl
FROM CurrentMonthTbl
END
From what I understand the problem is this:
When you run the below statement,
SELECT * into #temp1 FROM CurrentMonthTbl
you are creating a temp table on the fly.
If before that line you had a create table statement, then this Select into statement will fail because the table already exists.
If in your case you already have a temp table created, then try replacing:
SELECT * into #temp1 FROM CurrentMonthTbl
with:
Insert into #temp1
Select * from CurrentMonthTbl
Also look at There is already an object named '##Temp' in the database
You can use actual table in place of #temp1 table in if else statement. After that you can insert the data from actual to temp table and drop the actual table.
IF OBJECT_ID('tempdb..#temp1') is not null
drop table #temp1
IF (select BusinessDayCount from Calendartbl) <= 1
BEGIN
SELECT * into dbo.TempTable
FROM PreviousMonthTbl
END
ELSE
BEGIN
SELECT * into dbo.TempTable
FROM CurrentMonthTbl
END
select * into #temp1
from dbo.TempTable
IF OBJECT_ID('dbo.TempTable', 'U') is not null
drop table dbo.TempTable

Select with IN and Like

I have a very interesting problem. I have an SSRS report with a multiple select drop down.
The drop down allows to select more than one value, or all values.
All values is not the problem.
The problem is 1 or the combination of more than 1 option
When I select in the drop down 'AAA' it should return 3 values: 'AAA','AAA 1','AAA 2'
Right now is only returning 1 value.
QUESTION:
How can make the IN statement work like a LIKE?
The Drop down select
SELECT '(All)' AS team, '(All)' AS Descr
UNION ALL
SELECT 'AAA' , 'AAA'
UNION ALL
SELECT 'BBB' , 'BBB'
Table Mytable
ColumnA Varchar(5)
Values for ColumnA
'AAA'
'AAA 1'
'AAA 2'
'BBB'
'BBB 1'
'BBB 2'
SELECT * FROM Mytable
WHERE ColumnA IN (SELECT * FROM SplitListString(#Team, ',')))
Split function
CREATE FUNCTION [dbo].[SplitListString]
(#InputString NVARCHAR(max), #SplitChar CHAR(1))
RETURNS #ValuesList TABLE
(
param NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #ListValue NVARCHAR(max)
DECLARE #TmpString NVARCHAR(max)
DECLARE #PosSeparator INT
DECLARE #EndValues BIT
SET #TmpString = LTRIM(RTRIM(#InputString));
SET #EndValues = 0
WHILE (#EndValues = 0) BEGIN
SET #PosSeparator = CHARINDEX(#SplitChar, #TmpString)
IF (#PosSeparator) > 1 BEGIN
SELECT #ListValue = LTRIM(RTRIM(SUBSTRING(#TmpString, 1, #PosSeparator -1 )))
END
ELSE BEGIN
SELECT #ListValue = LTRIM(RTRIM(#TmpString))
SET #EndValues = 1
END
IF LEN(#ListValue) > 0 BEGIN
INSERT INTO #ValuesList
SELECT #ListValue
END
SET #TmpString = LTRIM(RTRIM(SUBSTRING(#TmpString, #PosSeparator + 1, LEN(#TmpString) - #PosSeparator)))
END
RETURN
END
You can't. But, you can make the like work like the like:
select *
from mytable t join
SplitListString(#Team, ',') s
on t.ColumnA like '%'+s.param+'%'
That is, move the split list to an explicit join. Replace with the actual column name returned by the function, and use the like function.
Or, if you prefer:
select *
from mytable t cross join
SplitListString(#Team, ',') s
where t.ColumnA like '%'+s.param+'%'
The two versions are equivalent and should produce the same execution plan.
Better approach would be to have a TeamsTable (teamID, teamName, ...) and teamMembersTable (teamMemberID, teamID, teamMemberDetails, ...).
Then you an build your dropdown list as
SELECT ... FROM TeamsTable ...;
and
SELECT ... FROM teamMembersTable WHERE teamID IN (valueFromYourDropDown);
Or you can just store your teamID or teamName (or both) in your (equivalent of) teamMembersTable
You're not going to get IN to work the same as LIKE without a lot of work. You could do something like this though (and it would be nice to see some of your actual data though so we could give better solutions):
SELECT *
FROM table
WHERE LEFT(field,3) IN #Parameter
If you'd like better performance, create a code field on your table and update it like this:
UPDATE table
SET codeField = LEFT(field,3)
Then just add an index on that field and run this query to get your results:
SELECT *
FROM table
WHERE codeField IN #Parameter

is it possible to select EXISTS directly as a bit?

I was wondering if it's possible to do something like this (which doesn't work):
select cast( (exists(select * from theTable where theColumn like 'theValue%') as bit)
Seems like it should be doable, but lots of things that should work in SQL don't ;) I've seen workarounds for this (SELECT 1 where... Exists...) but it seems like I should be able to just cast the result of the exists function as a bit and be done with it.
No, you'll have to use a workaround.
If you must return a conditional bit 0/1 another way is to:
SELECT CAST(
CASE WHEN EXISTS(SELECT * FROM theTable where theColumn like 'theValue%') THEN 1
ELSE 0
END
AS BIT)
Or without the cast:
SELECT
CASE
WHEN EXISTS( SELECT 1 FROM theTable WHERE theColumn LIKE 'theValue%' )
THEN 1
ELSE 0
END
SELECT CAST(COUNT(*) AS bit) FROM MyTable WHERE theColumn like 'theValue%'
When you cast to bit
0 -> 0
everything else -> 1
And NULL -> NULL of course, but you can't get NULL with COUNT(*) without a GROUP BY
bit maps directly to boolean in .net datatypes, even if it isn't really...
This looks similar but gives no row (not zero) if no matches, so it's not the same
SELECT TOP 1 CAST(NumberKeyCOlumn AS bit) FROM MyTable WHERE theColumn like 'theValue%'
You can use IIF and CAST
SELECT CAST(IIF(EXISTS(SELECT * FROM theTable
where theColumn like 'theValue%'), 1, 0) AS BIT)
I'm a bit late on the uptake for this; just stumbled across the post. However here's a solution which is more efficient & neat than the selected answer, but should give the same functionality:
declare #t table (name nvarchar(16))
declare #b bit
insert #t select N'Simon Byorg' union select N'Roe Bott'
select #b = isnull((select top 1 1 from #t where name = N'Simon Byorg'),0)
select #b whenTrue
select #b = isnull((select top 1 1 from #t where name = N'Anne Droid'),0)
select #b whenFalse
You can also do the following:
SELECT DISTINCT 1
FROM theTable
WHERE theColumn LIKE 'theValue%'
If there are no values starting with 'theValue' this will return null (no records) rather than a bit 0 though
SELECT IIF(EXISTS(SELECT * FROM theTable WHERE theColumn LIKE 'theValue%'), 1, 0)
No it isn't possible. The bit data type is not a boolean data type. It is an integer data type that can be 0,1, or NULL.
Another solution is to use ISNULL in tandem with SELECT TOP 1 1:
SELECT ISNULL((SELECT TOP 1 1 FROM theTable where theColumn like 'theValue%'), 0)
I believe exists can only be used in a where clause, so you'll have to do a workaround (or a subquery with exists as the where clause). I don't know if that counts as a workaround.
What about this:
create table table1 (col1 int null)
go
select 'no items',CONVERT(bit, (select COUNT(*) from table1) ) -- returns 'no items', 0
go
insert into table1 (col1) values (1)
go
select '1 item',CONVERT(bit, (select COUNT(*) from table1) ) --returns '1 item', 1
go
insert into table1 (col1) values (2)
go
select '2 items',CONVERT(bit, (select COUNT(*) from table1) ) --returns '2 items', 1
go
insert into table1 (col1) values (3)
go
drop table table1
go

Deleting duplicate record from table - SQL query

I need to delete duplicate rows only from the table, like I have 3 duplicate rows in the table, my query will delete 2 rows from 3 duplicated rows.
How can I get this? Please help me.
Please try the below query, it will definitely meet your objective
SET ROWCOUNT 1
DELETE test
FROM test a
WHERE (SELECT COUNT(*) FROM test b WHERE b.name = a.name) > 1
WHILE ##rowcount > 0
DELETE test
FROM test a
WHERE (SELECT COUNT(*) FROM test b WHERE b.name = a.name) > 1
SET ROWCOUNT 0
where test is your table name
This works in SQL Server although it isn't a single statement:
Declare #cnt int;
Select #cnt=COUNT(*) From DupTable Where (Col1=1); -- Assumes you are trying to delete the duplicates where some condition (e.g. Col1=1) is true.
Delete Top (#cnt-1) From DupTable
It also doesn't require any extra assumptions (like the existance of another column that makes each row unique). After all, Santanu did say that the rows were duplicates and not just the one column.
However, the right answer, in my view, is to get a real table structure. That is, add an IDENTITY column to this table so that you can use a single SQL command to do your work. Like this:
ALTER TABLE dbo.DupTable ADD
IDCol int NOT NULL IDENTITY (1, 1)
GO
Then the delete is trivial:
DELETE FROM DupTable WHERE IDCol NOT IN
(SELECT MAX(IDCol) FROM DupTable GROUP BY Col1, Col2, Col3)
DELETE FROM Table t1, Table t2 WHERE t1.colDup = t2.colDup AND t1.date < t2.date
Will delete every duplicate row from Table (on column colDup) except the oldest (i.e. lowset date).
DELETE FROM `mytbl`
INNER JOIN (
SELECT 1 FROM `mytbl`
GROUP BY `duplicated_column` HAVING COUNT(*)=2
) USING(`id`)
Edit:
My bad, the above query won't work.
Assuming table structure:
id int auto_increment
num int # <-- this is the column with duplicated values
The following query would work in MySQL (i checked):
DELETE `mytbl` FROM `mytbl`
INNER JOIN
(
SELECT `num` FROM `mytbl`
GROUP BY `num` HAVING COUNT(*)=2
) AS `tmp` USING (`num`)
The query would delete the rows that have 2 (not more or else) duplicated values in the num column.
Edit (again):
I suggest to add a key on the num column.
Edit(#3):
In case that the author wanted to delete the duplicated rows, the following should work for MySQL (it worked for me):
DELETE `delete_duplicated_rows` FROM `delete_duplicated_rows`
NATURAL JOIN (
SELECT *
FROM `delete_duplicated_rows`
GROUP BY `num1` HAVING COUNT(*)=2
) AS `der`
While assuming table structure is:
CREATE TABLE `delete_duplicated_rows` (
`num1` tinyint(4) DEFAULT NOT NULL,
`num2` tinyint(4) DEFAULT NOT NULL
) ENGINE=MyISAM;
If you have the id's of the rows you want to delete then...
DELETE FROM table WHERE id IN (1, 4, 7, [id numbers to delete...])
I think each table has unique identifier.
So if it exists then you can write following query:
Delete Table1 from Table1 t1 where 2 >= (select count(id) from Table1 where dupColumn = t1.dupColumn) and
t1.id not in (select max (id) from Table1 where dupColumn = t1.dupColumn)
OOps. It seems it is possible to use second filter only
Delete Table1 from Table1 t1 where
t1.id not in (select max (id) from Table1 where dupColumn = t1.dupColumn)
-- Just to demonstrates Marks example
.
-- START === 1.0.dbo..DuplicatesTable.TableCreate.sql
/****** Object: Table [dbo].[DuplicatesTable]
Script Date: 03/29/2010 21:24:02 ******/
IF EXISTS (SELECT * FROM sys.objects
WHERE
object_id = OBJECT_ID(N'[dbo].[DuplicatesTable]')
AND type in (N'U'))
DROP TABLE [dbo].[DuplicatesTable]
GO
/****** Object: Table [dbo].[DuplicatesTable]
Script Date: 03/29/2010 21:24:02 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[DuplicatesTable](
[ColA] [varchar](10) NOT NULL, -- the name of the DuplicatesTable
[ColB] [varchar](10) NULL, -- the description of the e DuplicatesTable
)
/*
<doc>
Models a DuplicatesTable for
</doc>
*/
GO
--============================================================ DuplicatesTable START
declare #ScriptFileName varchar(2000)
SELECT #ScriptFileName = '$(ScriptFileName)'
SELECT #ScriptFileName + ' --- DuplicatesTable START ========================================='
declare #TableName varchar(200)
select #TableName = 'DuplicatesTable'
SELECT 'SELECT name from sys.tables where name =''' + #TableName + ''''
SELECT name from sys.tables
where name = #TableName
DECLARE #TableCount INT
SELECT #TableCount = COUNT(name ) from sys.tables
where name =#TableName
if #TableCount=1
SELECT ' DuplicatesTable PASSED. The Table ' + #TableName + ' EXISTS '
ELSE
SELECT ' DuplicatesTable FAILED. The Table ' + #TableName + ' DOES NOT EXIST '
SELECT #ScriptFileName + ' --- DuplicatesTable END ========================================='
--============================================================ DuplicatesTable END
GO
-- END === 1.0.dbo..DuplicatesTable.TableCreate.sql
.
-- START === 1.1..dbo..DuplicatesTable.TableInsert.sql
BEGIN TRANSACTION;
INSERT INTO [dbo].[DuplicatesTable]([ColA], [ColB])
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1'
COMMIT;
RAISERROR (N'[dbo].[DuplicatesTable]: Insert Batch: 1.....Done!', 10, 1) WITH NOWAIT;
GO
-- END === 1.1..dbo..DuplicatesTable.TableInsert.sql
.
-- START === 2.0.RemoveDuplicates.Script.sql
ALTER TABLE dbo.DuplicatesTable ADD
DuplicatesTableId int NOT NULL IDENTITY (1, 1)
GO
-- Then the delete is trivial:
DELETE FROM dbo.DuplicatesTable WHERE DuplicatesTableId NOT IN
(SELECT MAX(DuplicatesTableId) FROM dbo.DuplicatesTable GROUP BY ColA , ColB)
Select * from DuplicatesTable ;
-- END === 2.0.RemoveDuplicates.Script.sql