Display the row by row wise - sql

Using SQL Server 2000
table1
ID Value
101 100
102 200
103 500
I have only 3 row in the table. I want to make in row wise view
Expected Output
101 102 103
100 200 500
How to make a select query for the above condition.
Need Query Help

If you defenitely know which values you have in ID column you can use query like this:
SELECT
MAX(id_101) AS id_101,
MAX(id_102) AS id_102,
MAX(id_103) AS id_103
FROM (
SELECT
1 AS aux,
CASE WHEN ID = 101 THEN val ELSE null END AS id_101,
CASE WHEN ID = 102 THEN val ELSE null END AS id_102,
CASE WHEN ID = 103 THEN val ELSE null END AS id_103
FROM table1
) AS t(aux, id_101, id_102, id_103)
GROUP BY t.aux;

Assuming that 101, 102, 103 is a column names you can rotate table usign PIVOT:
SELECT *
FROM
(
SELECT id, value
FROM #data1
) p
PIVOT (SUM(value) FOR [id] IN ([101], [102], [103])) AS pvt
Prepare data:
DECLARE #data1 TABLE(id int, value INT)
INSERT INTO #data1 VALUES(101, 100)
INSERT INTO #data1 VALUES(102, 200)
INSERT INTO #data1 VALUES(103, 500)

Related

SQL insert if last value is different

Using SQL Server 2005/2008 I would like to insert a new row if the last value (sorted by _timestamp) inserted is not the same value.
For example:
value | timestamp
100 | "yesterday"
101 | "today"
For the next operation:
A value of 101 should not be inserted as this is the latest value
However a value of 102 should be inserted as the latest value is not this
Why you don't use something like that?
DECLARE #table TABLE(val INT, [timestamp] DATETIME)
INSERT INTO #table
SELECT 100, N'20160112'
UNION ALL
SELECT 101, N'20160113'
SELECT * FROM #table
INSERT INTO #table
SELECT 101, N'20160114'
WHERE 101 <> ISNULL((SELECT TOP 1 val FROM #table
ORDER BY timestamp DESC), -1)
SELECT * FROM #table AS T

How to generate a new code

Using VB.Net and SQL Server
Table1
Id Value .....
1001P0010001 100
1001P0010002 200
1001P0010003 300
1001P0010004 400
...
I have n columns and rows in table1, from the table1, I want to copy all the column details with new id no...
id no is like this 1001P0020001, 1001P0020002, .......
P002 is next id, P003 is the next Id.....
The first 4 digits and last 4 digits will remain as read from table1, middle 4 digits should change to next series
Expected output
Id Value .....
1001P0010001 100
1001P0010002 200
1001P0010003 300
1001P0010004 400
1001P0020001 100
1001P0020002 200
1001P0020003 300
1001P0020004 400
...
Which the best way to do this?
I can do it in VB.Net or a SQL query...? Please suggest ways of doing this.
CREATE TABLE CocoJambo (
Id CHAR(12) NOT NULL,
Value INT NULL,
CHECK( Id LIKE '[0-9][0-9][0-9][0-9][A-Z][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' )
);
GO
CREATE UNIQUE INDEX IUN_CocoJambo_Id
ON CocoJambo (Id);
GO
INSERT CocoJambo (Id, Value)
SELECT '1001P0010001', 100
UNION ALL SELECT '1001P0010002', 200
UNION ALL SELECT '1001P0010003', 300
UNION ALL SELECT '1001P0010004', 400
UNION ALL SELECT '1001P0020001', 100
UNION ALL SELECT '1001P0020002', 200
UNION ALL SELECT '1001P0020003', 300
UNION ALL SELECT '1001P0020004', 400;
GO
-- Test 1: generating a single Id
DECLARE #Prefix CHAR(5),
#Sufix CHAR(4);
SELECT #Prefix = '1001P',
#Sufix = '0001';
BEGIN TRAN
DECLARE #LastGeneratedMiddleValue INT,
#LastValue INT;
SELECT #LastGeneratedMiddleValue = y.MiddleValue,
#LastValue = y.Value
FROM
(
SELECT x.MiddleValue, x.Value,
ROW_NUMBER() OVER(ORDER BY x.MiddleValue DESC) AS RowNum
FROM
(
SELECT CONVERT(INT,SUBSTRING(a.Id,6,3)) AS MiddleValue, a.Value
FROM CocoJambo a WITH(UPDLOCK) -- It will lock the rows (U lock) during transaction
WHERE a.Id LIKE #Prefix+'%'+#Sufix
) x
) y
WHERE y.RowNum=1;
SELECT #LastGeneratedMiddleValue = ISNULL(#LastGeneratedMiddleValue ,0)
SELECT #Prefix
+RIGHT('00'+CONVERT(VARCHAR(3),#LastGeneratedMiddleValue +1),3)
+#Sufix AS MyNewId,
#LastValue AS Value
COMMIT TRAN;
GO
-- Test 2: generating many Id's
BEGIN TRAN
DECLARE #Results TABLE (
Prefix CHAR(5) NOT NULL,
Sufix CHAR(4) NOT NULL,
LastGeneratedMiddleValue INT NOT NULL,
LastValue INT NULL
);
INSERT #Results (Prefix, Sufix, LastGeneratedMiddleValue, LastValue)
SELECT y.Prefix, y.Sufix, y.MiddleValue, y.Value
FROM
(
SELECT x.Prefix, x.MiddleValue, x.Sufix, x.Value,
ROW_NUMBER() OVER(PARTITION BY x.Prefix, x.Sufix ORDER BY x.MiddleValue DESC) AS RowNum
FROM
(
SELECT SUBSTRING(a.Id,1,5) AS Prefix,
CONVERT(INT,SUBSTRING(a.Id,6,3)) AS MiddleValue,
SUBSTRING(a.Id,9,4) AS Sufix,
a.Value
FROM CocoJambo a WITH(UPDLOCK) -- It will lock the rows (U lock) during transaction
) x
) y
WHERE y.RowNum=1;
SELECT r.*,
r.Prefix
+RIGHT('00'+CONVERT(VARCHAR(3),r.LastGeneratedMiddleValue +1),3)
+r.Sufix AS MyNewId,
r.LastValue AS Value
FROM #Results r;
COMMIT TRAN;
GO
insert into table1 (id, value)
select
l +
replicate('0', 3 - lenght(m)) + m +
r,
value
from (
select
left(id, 5) l,
cast(cast(substring(id, 6, 3) as integer) + 1 as varchar(3)) m,
right(id, 4),
value
from table1
) s

How to get the range between two rows

Table1
ID Value
001 100
002 125
003 150
004 175
005 200
006 225
...
Expected Output
If the user enters a value between 100 to 124, then id should display 001
If the user enters a value between 125 to 149, then id should display 002
If the user enters a value between 200 to 224, then id should display 005
If the user enters a value between 225 to 249, then id should display 006
How to make a query for the above condition.
Need query help
It'd be easier to write query to transformed table like ID, ValueFrom, ValueTo.
For this table:
SELECT MAX(ID)
FROM Table1
WHERE Value <= #value
Basically, if 155 is entered, IDs 1 2 and 3 are returned, then MAX ID is taken (3) which is the answer.
Here you go:
First create the test table:
CREATE TABLE #Temp(ID INT, Val INT)
INSERT INTO #Temp VALUES(1, 100);
INSERT INTO #Temp VALUES(2, 125);
INSERT INTO #Temp VALUES(3, 150);
INSERT INTO #Temp VALUES(4, 175);
INSERT INTO #Temp VALUES(5, 200);
INSERT INTO #Temp VALUES(6, 225);
Set up the test value
DECLARE #value INT
SET #value = 125
If ID is sequential (i.e. 1, 2, 3, 4, 5, etc)
SELECT t1.id
FROM #Temp t1, #Temp t2
WHERE t1.ID = t2.ID -1
AND #value BETWEEN t1.Val AND t2.Val -1
If ID is not sequential (i.e. 1, 2, 5, 7, 8, etc)
;WITH cte AS (SELECT ROW_NUMBER() OVER (ORDER BY id) AS rownum, ID, Val FROM #Temp)
SELECT t1.id
FROM cte t1, cte t2
WHERE t1.rownum = t2.rownum -1
AND #value BETWEEN t1.Val AND t2.Val -1
Get the closest match and return first row previously sorting by value:
select top 1 id
from range
where value <= #value
order by value desc
Or, if you need to incorporate this query into another:
select id
from range
where value = (select max(value) from range where value <= #value)
Use CASE in SELECT statement....
Eg:
declare #c int;
set #c=120;
SELECT
CASE
WHEN #c BETWEEN 100 AND 124 THEN '001'
WHEN #c BETWEEN 125 AND 149 THEN '002'
ELSE 'Other'
END

SQL Query to return rows where a list of numbers is between start and end values

There is a table in Oracle with the columns:
id | start_number | end_number
---+--------------+------------
1 | 100 | 200
2 | 151 | 200
3 | 25 | 49
4 | 98 | 99
5 | 49 | 100
There is a list of numbers (50, 99, 150).
I want an sql statement that returns all the ids where any of the numbers in the list of numbers is found equal to or between the start_number and the end_number.
Using the above example; 1, 4 and 5 should be returned.
1 - 150 is between or equal to 100 and 200
2 - none of the numbers are between or equal to 151 and 200
3 - none of the numbers are between or equal to 25 and 49
4 - 99 is between or equal to 98 and 99
5 - 50 and 99 are between or equal to 49 and 100
drop table TEMP_TABLE;
create table TEMP_TABLE(
THE_ID number,
THE_START number,
THE_END number
);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (1, 100, 200);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (2, 151, 200);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (3, 25, 49);
insert into TEMP_TABLE(THE_ID, THE_START, THE_END) values (4, 98, 99);
insert into TEMP_TABLE(the_id, the_start, the_end) values (5, 49, 100);
The following is the solution I came up with based on the comments and answers below plus some additional research:
SELECT
*
from
TEMP_TABLE
where
EXISTS (select * from(
select column_value as id
from table(SYS.DBMS_DEBUG_VC2COLL(50,99,150))
)
where id
BETWEEN TEMP_TABLE.the_start AND TEMP_TABLE.the_end
)
This works too:
SELECT
*
from
TEMP_TABLE
where
EXISTS (select * from(
select column_value as id
from table(sys.ku$_vcnt(50,99,150))
)
where id
BETWEEN TEMP_TABLE.the_start AND TEMP_TABLE.the_end
)
Here is a full example:
create table #list (
number int
)
create table #table (
id int,
start_number int,
end_number int
)
insert into #list values(50)
insert into #list values(99)
insert into #list values(150)
insert into #table values(1,100,200)
insert into #table values(2,151,200)
insert into #table values(3,25,49)
insert into #table values(4,98,99)
insert into #table values(5,49,100)
select distinct a.* from #table a
inner join #list l --your list of numbers
on l.number between a.start_number and a.end_number
drop table #list
drop table #table
You'll simply need to remove the code about #table (create, insert and drop) and put your table in the select.
It partly depends on how your are storing your list of numbers. I'll assume that they're in another table for now, as even then you have many options.
SELECT
*
FROM
yourTable
WHERE
EXISTS (SELECT * FROM yourList WHERE number BETWEEN yourTable.start_number AND yourTable.end_number)
Or...
SELECT
*
FROM
yourTable
INNER JOIN
yourList
ON yourList.number BETWEEN yourTable.start_number AND yourTable.end_number
Both of those are the simplest expressions, and work well for small data sets. If your list of numbers is relatively small, and your original data is relatively large, however, this may not scale well. This is because both of the above scan the whole of yourTable and then check each record against yourList.
What may be preferable is to scan the list, and then attempt to use indexes to check against the original data. This would require you to be able to reverse the BETWEEN statement to yourTable.start_number BETWEEN x and y
This can only be done if you know the maximum gap between start_number and end_number.
SELECT
*
FROM
yourList
INNER JOIN
yourTable
ON yourTable.end_number >= yourList.number
AND yourTable.start_number <= yourList.number
AND yourTable.start_number >= yourList.number - max_gap
To achieve this I would store the value of max_gap in another table, and update it as the values in yourTable change.
You will want to create a temporary table to hold your numbers, if the numbers aren't already in one. Then it becomes relatively simple:
SELECT DISTINCT mt.ID FROM MyTable mt
INNER JOIN TempTable tt --your list of numbers
ON tt.number Between mt.start_number and mt.end_number
To create the table based on an array of passed values, you can use table definitions in your procedure. I'm light on Oracle syntax and don't have TOAD handy, but you should be able to get something like this to work:
CREATE OR REPLACE PROCEDURE FindIdsFromList
AS
DECLARE
TYPE NumberRecord IS RECORD (Number int NOT NULL)
TYPE NumberList IS TABLE OF NumberRecord;
NumberList myNumberList;
BEGIN
myNumberList := (50,99,150);
SELECT DISTINCT mt.ID FROM MyTable mt
INNER JOIN myNumberList nt --your list of numbers
ON nt.Number Between mt.start_number and mt.end_number
END

TSQL- generate a sequence number for duplicate records

Using SQL Server 2000, consider a source table with more than 400,000 records.
The task is to select each regno entry with an incrementing on-the-fly rowid or sequence number for those with duplicates or multiple entries. For those which do NOT have duplicate entries in the source table, the rowid should simply be null.
Here's an example of the desired output:
regno rowid
100 1
100 2
100 3
200 null
300 4
300 5
400 null
500 null
600 6
600 7
Question:
What query would do the desired sequence incrementing using TSQL in SQL Server 2000?
If my comment is correct (600 should be 6,7) then have a look at this
DECLARE #Table TABLE(
regno INT,
rowid INT
)
INSERT INTO #Table (regno,rowid) SELECT 100, NULL
INSERT INTO #Table (regno,rowid) SELECT 100, NULL
INSERT INTO #Table (regno,rowid) SELECT 100, NULL
INSERT INTO #Table (regno,rowid) SELECT 200, NULL
INSERT INTO #Table (regno,rowid) SELECT 300, NULL
INSERT INTO #Table (regno,rowid) SELECT 300, NULL
INSERT INTO #Table (regno,rowid) SELECT 400, NULL
INSERT INTO #Table (regno,rowid) SELECT 500, NULL
INSERT INTO #Table (regno,rowid) SELECT 600, NULL
INSERT INTO #Table (regno,rowid) SELECT 600, NULL
DECLARE #TempTable TABLE(
ID INT IDENTITY(1,1),
regno INT
)
INSERT INTO #TempTable (regno)
SELECT regno
FROM #Table
SELECT regno,
CASE
WHEN (SELECT COUNT(1) FROM #TempTable WHERE regno = t.regno) = 1
THEN NULL
ELSE (SELECT COUNT(1) FROM #TempTable WHERE regno = t.regno) - (SELECT COUNT(1) FROM #TempTable WHERE regno = t.regno AND ID > t.ID) +
(SELECT COUNT(1) FROM #TempTable WHERE regno < t.regno AND regno IN (SELECT regno FROM #TempTable GROUP BY regno having COUNT(1) > 1))
END Val
FROM #TempTable t
The query to extract the non-unique records would be
select regno,count(*) from table group by regno having count(*) > 1
I don't know enough about MSSQL to tell you how to generate an incrementing sequence number to update the records that match the query.
Without a temp table:
DECLARE #Table TABLE(
regno INT
)
INSERT INTO #Table (regno) SELECT 100
INSERT INTO #Table (regno) SELECT 100
INSERT INTO #Table (regno) SELECT 100
INSERT INTO #Table (regno) SELECT 200
INSERT INTO #Table (regno) SELECT 300
INSERT INTO #Table (regno) SELECT 300
INSERT INTO #Table (regno) SELECT 400
INSERT INTO #Table (regno) SELECT 500
INSERT INTO #Table (regno) SELECT 600
INSERT INTO #Table (regno) SELECT 600
select regno, null as rowid from #Table group by regno having count(*) = 1
union
select regno, row_number() OVER (ORDER BY a.regno) as rowid
from #table a
where regno in (select regno from #table group by regno having count(*) > 1)
regno rowid
----------- --------------------
100 1
100 2
100 3
200 NULL
300 4
300 5
400 NULL
500 NULL
600 6
600 7
Oops - did not see that you want to do this in SQL 2000 until after posting this ... ignore my query please. In SQL 2000 you need a temp table to generate the sequence.