I have this column in my table and I want to get all skipped transactions (which is a varchar)
SA1
SA3
SA50
SA999
I'm trying to get
SA2
SA4 to SA49
SA51 to SA998
EDIT: I've checked the actual data, found out that it's non-trailing zeroes.
I've done this with PHP. Was wondering if is there a way within SQL to do it?
This might sound dumb, but what I'm trying is to plot it like this (this returns null values)
WITH cte (id) AS (
SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM sys.all_columns AS s1
CROSS JOIN sys.all_columns AS s2
),
table1 AS (
SELECT sNumber as id1 FROM Sales WHERE sNumber LIKE '%SI_'
),
table2 AS (
SELECT sNumber as id1 FROM Sales WHERE sNumber LIKE '%SI__'
),
table3 AS (
SELECT sNumber as id1 FROM Sales WHERE sNumber LIKE '%SI___'
)
SELECT
'SA' + RIGHT('' + CAST(t1.id AS VARCHAR(2)), 1) AS id_missing
FROM cte t1
LEFT JOIN table1 t2
ON t1.id = CAST(RIGHT(t2.id1, 1) AS INT)
WHERE
t1.id < (SELECT MAX(CAST(RIGHT(id1, 1) AS INT)) FROM yourTable1) AND
t2.id1 IS NULL
UNION ALL
SELECT
'SA' + RIGHT('' + CAST(t1.id AS VARCHAR(2)), 2) AS id_missing
FROM cte t1
LEFT JOIN table2 t2
ON t1.id = CAST(RIGHT(t2.id2, 2) AS INT)
WHERE
t1.id < (SELECT MAX(CAST(RIGHT(id2, 2) AS INT)) FROM yourTable2) AND
t2.id2 IS NULL
UNION ALL
SELECT
'SA' + RIGHT('' + CAST(t1.id AS VARCHAR(3)), 3) AS id_missing
FROM cte t1
LEFT JOIN table3 t2
ON t1.id = CAST(RIGHT(t2.id3, 3) AS INT)
WHERE
t1.id < (SELECT MAX(CAST(RIGHT(id3, 3) AS INT)) FROM yourTable3) AND
t2.id3 IS NULL
You may use a calendar table approach with a left join here:
WITH cte (id) AS (
SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM sys.all_columns AS s1
CROSS JOIN sys.all_columns AS s2
)
SELECT
'SA' + RIGHT('000' + CAST(t1.id AS VARCHAR(3)), 3) AS id_missing
FROM cte t1
LEFT JOIN yourTable t2
ON t1.id = CAST(RIGHT(t2.id, 3) AS INT)
WHERE
t1.id < (SELECT MAX(CAST(RIGHT(id, 3) AS INT)) FROM yourTable) AND
t2.id IS NULL;
Demo
The idea is to generate a sequence of numbers covering the possible up to 1000 values which might appear in your current table as SAxxx. Then, we left join this calendar table to your current table, on the condition that the numeric portion of the id does not match. All such non matching SAxxx values are then retained in the result set.
How to optimize the following query to be work better :
SELECT c.a1,c.a2,
(SELECT SUM(t2.TempOB) FROM tbl1 t2 WHERE t2.AccNo LIKE CONCAT( C.AccNo,'%') )OB,
(SELECT SUM(t3.TempDebit) FROM tbl1 t3 WHERE t3.AccNo LIKE CONCAT( C.AccNo,'%') ) Debit,
(SELECT SUM(t4.TempCredit) FROM tbl1 t4 WHERE t4.AccNo LIKE CONCAT( C.AccNo,'%') ) Credit
FROM tbl1 C WHERE AccLevel= #Level
You can use as the below:
SELECT
A.a1,
A.a2,
SUM(B.OB) AS OB,
SUM(B.Debit) AS Debit,
SUM(B.Credit) AS Credit
FROM
tbl1 A LEFT JOIN
tbl1 B ON B.AccNo LIKE A.AccNo + '%'
WHERE
A.AccLevel = #Level
GROUP BY
A.a1,
A.a2
I have two tables
Table 1, columns: A, B, C
Table 2, columns: A, D, E
I want to select all from table 1 with an additional field added.
If the contents of string column table_1.A exists in table_2.A, then TRUE, if not then FALSE.
I'd love to tell you what I've tried, but nothing is coming close. I can do this with a SELECT CASE statement, but I can't figure out how to select all at the same time.
Thanks
Try using CASE
SELECT
table1.A,
table1.B,
table1.C,
CASE WHEN table2.A IS NULL THEN 'FALSE' ELSE 'TRUE' END
FROM
table1
LEFT OUTER JOIN
table2
ON table1.A = table2.A
SELECT T1.*, IIF(T2.D IS NULL, 'FALSE', 'TRUE')
FROM Table1 T1
LEFT JOIN Table2 T2 ON T2.A LIKE '%' + T1.A + '%'
You need a left outer join and them compare both tables using the case when columnab is not null then true else false
This would give you only one row per record in Table1.
SELECT Table1.*,
ISNULL([Found],'False') [Found]
FROM Table1
OUTER APPLY (
SELECT TOP 1
'True' AS [Found]
FROM Table2
WHERE Table2.A LIKE '%' + Table1.A + '%'
)
I have 2 name columns from table1.name and table2.name. I have names in table1.name like "Alex Testing" and in table2.name it's "Alexander Testing". I have the table do some other tricky stuff but it doesn't recognize that Alex and Alexander are the same people so it will not include the name in my report. I was wondering if there was a way I could get these 2 to inner join by first name or even by last name, like if another table had the same first name but different last name?
I've tried:
SELECT
Table1.[Name], Table2.[Time],
CASE WHEN myvariables here then 0 ELSE 1 END AS columnB
INTO NewTable
FROM
Table1 INNER JOIN Table2
ON Table1.[Name] LIKE ('%' + Table2.Name + '%')
however it still does not work, it wont recognize Alex's name.
I've also tried:
SELECT
Table1.[Name], Table2.[Time],
CASE WHEN myvariables here THEN 0 ELSE 1 END as columnB
INTO NewTable
FROM
Table1 INNER JOIN Table2
ON Table1.[Name] LIKE CONCAT('%',"Table2.Name", '%')
Try:
SELECT
Table1.[Name], Table2.[Time],
CASE WHEN myvariables here then 0 ELSE 1 END AS columnB
INTO NewTable
FROM
Table1 INNER JOIN Table2
ON SUBSTRING(Table1.[Name], CHARINDEX(' ', Table1.[Name]) + 1, LEN(Table1.[Name])) = SUBSTRING(Table2.[Name], CHARINDEX(' ', Table2.[Name]) + 1, LEN(Table2.[Name]))
If you have large volume tables you may want to use subqueries and select directly lastnames, and then use a join on lastnames.
UNPIVOT will not return NULLs, but I need them in a comparison query. I am trying to avoid using ISNULL the following example (Because in the real sql there are over 100 fields):
Select ID, theValue, column_name
From
(select ID,
ISNULL(CAST([TheColumnToCompare] AS VarChar(1000)), '') as TheColumnToCompare
from MyView
where The_Date = '04/30/2009'
) MA
UNPIVOT
(theValue FOR column_name IN
([TheColumnToCompare])
) AS unpvt
Any alternatives?
To preserve NULLs, use CROSS JOIN ... CASE:
select a.ID, b.column_name
, column_value =
case b.column_name
when 'col1' then a.col1
when 'col2' then a.col2
when 'col3' then a.col3
when 'col4' then a.col4
end
from (
select ID, col1, col2, col3, col4
from table1
) a
cross join (
select 'col1' union all
select 'col2' union all
select 'col3' union all
select 'col4'
) b (column_name)
Instead of:
select ID, column_name, column_value
From (
select ID, col1, col2, col3, col4
from table1
) a
unpivot (
column_value FOR column_name IN (
col1, col2, col3, col4)
) b
A text editor with column mode makes such queries easier to write. UltraEdit has it, so does Emacs. In Emacs it's called rectangular edit.
You might need to script it for 100 columns.
It's a real pain. You have to switch them out before the UNPIVOT, because there is no row produced for ISNULL() to operate on - code generation is your friend here.
I have the problem on PIVOT as well. Missing rows turn into NULL, which you have to wrap in ISNULL() all the way across the row if missing values are the same as 0.0 for example.
I ran into the same problem. Using CROSS APPLY (SQL Server 2005 and later) instead of Unpivot solved the problem. I found the solution based on this article An Alternative (Better?) Method to UNPIVOT
and I made the following example to demonstrate that CROSS APPLY will NOT Ignore NULLs like Unpivot.
create table #Orders (OrderDate datetime, product nvarchar(100), ItemsCount float, GrossAmount float, employee nvarchar(100))
insert into #Orders
select getutcdate(),'Windows',10,10.32,'Me'
union
select getutcdate(),'Office',31,21.23,'you'
union
select getutcdate(),'Office',31,55.45,'me'
union
select getutcdate(),'Windows',10,null,'You'
SELECT OrderDate, product,employee,Measure,MeasureType
from #Orders orders
CROSS APPLY (
VALUES ('ItemsCount',ItemsCount),('GrossAmount',GrossAmount)
)
x(MeasureType, Measure)
SELECT OrderDate, product,employee,Measure,MeasureType
from #Orders orders
UNPIVOT
(Measure FOR MeasureType IN
(ItemsCount,GrossAmount)
)AS unpvt;
drop table #Orders
or, in SQLServer 2008 in shorter way:
...
cross join
(values('col1'), ('col2'), ('col3'), ('col4')) column_names(column_name)
Using dynamic SQL and COALESCE, I solved the problem like this:
DECLARE #SQL NVARCHAR(MAX)
DECLARE #cols NVARCHAR(MAX)
DECLARE #dataCols NVARCHAR(MAX)
SELECT
#dataCols = COALESCE(#dataCols + ', ' + 'ISNULL(' + Name + ',0) ' + Name , 'ISNULL(' + Name + ',0) ' + Name )
FROM Metric WITH (NOLOCK)
ORDER BY ID
SELECT
#cols = COALESCE(#cols + ', ' + Name , Name )
FROM Metric WITH (NOLOCK)
ORDER BY ID
SET #SQL = 'SELECT ArchiveID, MetricDate, BoxID, GroupID, ID MetricID, MetricName, Value
FROM
(SELECT ArchiveID, [Date] MetricDate, BoxID, GroupID, ' + #dataCols + '
FROM MetricData WITH (NOLOCK)
INNER JOIN Archive WITH (NOLOCK)
ON ArchiveID = ID
WHERE BoxID = ' + CONVERT(VARCHAR(40), #BoxID) + '
AND GroupID = ' + CONVERT(VARCHAR(40), #GroupID) + ') p
UNPIVOT
(Value FOR MetricName IN
(' + #cols + ')
)AS unpvt
INNER JOIN Metric WITH (NOLOCK)
ON MetricName = Name
ORDER BY MetricID, MetricDate'
EXECUTE( #SQL )
I've found left outer joining the UNPIVOT result to the full list of fields, conveniently pulled from INFORMATION_SCHEMA, to be a practical answer to this problem in some contexts.
-- test data
CREATE TABLE _t1(name varchar(20),object_id varchar(20),principal_id varchar(20),schema_id varchar(20),parent_object_id varchar(20),type varchar(20),type_desc varchar(20),create_date varchar(20),modify_date varchar(20),is_ms_shipped varchar(20),is_published varchar(20),is_schema_published varchar(20))
INSERT INTO _t1 SELECT 'blah1', 3, NULL, 4, 0, 'blah2', 'blah3', '20100402 16:59:23.267', NULL, 1, 0, 0
-- example
select c.COLUMN_NAME, Value
from INFORMATION_SCHEMA.COLUMNS c
left join (
select * from _t1
) q1
unpivot (Value for COLUMN_NAME in (name,object_id,principal_id,schema_id,parent_object_id,type,type_desc,create_date,modify_date,is_ms_shipped,is_published,is_schema_published)
) t on t.COLUMN_NAME = c.COLUMN_NAME
where c.TABLE_NAME = '_t1'
</pre>
output looks like:
+----------------------+-----------------------+
| COLUMN_NAME | Value |
+----------------------+-----------------------+
| name | blah1 |
| object_id | 3 |
| principal_id | NULL | <======
| schema_id | 4 |
| parent_object_id | 0 |
| type | blah2 |
| type_desc | blah3 |
| create_date | 20100402 16:59:23.26 |
| modify_date | NULL | <======
| is_ms_shipped | 1 |
| is_published | 0 |
| is_schema_published | 0 |
+----------------------+-----------------------+
Writing in May'22 with testing it on AWS Redshift.
You can use a with clause where you can coalesce the columns where nulls are expected. Alternatively, you can use coalesce in the select statement prior to the UNPIVOT block.
And don't forget to alias with the original column name (Not following won't break or violate the rule but would save some time for coffee).
Select ID, theValue, column_name
From
(select ID,
coalesce(CAST([TheColumnToCompare] AS VarChar(1000)), '') as TheColumnToCompare
from MyView
where The_Date = '04/30/2009'
) MA
UNPIVOT
(theValue FOR column_name IN
([TheColumnToCompare])
) AS unpvt
OR
WITH TEMP1 as (
select ID,
coalesce(CAST([TheColumnToCompare] AS VarChar(1000)), '') as TheColumnToCompare
from MyView
where The_Date = '04/30/2009'
)
Select ID, theValue, column_name
From
(select ID, TheColumnToCompare
from MyView
where The_Date = '04/30/2009'
) MA
UNPIVOT
(theValue FOR column_name IN
([TheColumnToCompare])
) AS unpvt
I had your same problem and this is
my quick and dirty solution :
your query :
select
Month,Name,value
from TableName
unpivot
(
Value for Name in (Col_1,Col_2,Col_3,Col_4,Col_5
)
) u
replace with :
select Month,Name,value from
( select
isnull(Month,'no-data') as Month,
isnull(Name,'no-data') as Name,
isnull(value,'no-data') as value from TableName
) as T1
unpivot
(
Value
for Name in (Col_1,Col_2,Col_3,Col_4,Col_5)
) u
ok the null value is replaced with a string, but all rows will be returned !!
ISNULL is half the answer. Use NULLIF to translate back to NULL. E.g.
DECLARE #temp TABLE(
Foo varchar(50),
Bar varchar(50) NULL
);
INSERT INTO #temp( Foo,Bar )VALUES( 'licious',NULL );
SELECT * FROM #temp;
SELECT
Col,
NULLIF( Val,'0Null' ) AS Val
FROM(
SELECT
Foo,
ISNULL( Bar,'0Null' ) AS Bar
FROM
#temp
) AS t
UNPIVOT(
Val FOR Col IN(
Foo,
Bar
)
) up;
Here I use "0Null" as my intermediate value. You can use anything you like. However, you risk collision with user input if you choose something real-world like "Null". Garbage works fine "!##34())0" but may be more confusing to future coders. I am sure you get the picture.