Rows without repeating records - sql

id | name
-------+-------------------------------------
209096 | Pharmacy
204200 | Eyecare Center
185718 | Duffy PC
214519 | Shopko
162225 | Edward Jones
7609 | Back In Action Chiropractic Center
I use select id, name from customer order by random()
There are 6 records i just want that when ever i query, i will get a unique row each time for six times and then it starts again from first or the records are ordered each time that the top one did't repeat

This will give you 6 random rows each time. The Group By is to ensure unique rows if your id is not a unique primary key, so maybe not needed - depending on your table structure.
SELECT TOP 6 id, name, ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) AS [RandomNumber]
FROM customer
GROUP BY id,name
ORDER BY [RandomNumber]
Edit: Sorry! Didn't read the question properly. Although you can use this to get a random row each time :)
If you want to specifically get all 6 rows in a random order 1 at a time you will need to store the order somewhere. Suggest creating a temp table and selecting from there, or if you are using a front end webpage get all 6 rows and store in a dataset.

You can use that logic,
"milisecond" part of current date is always changing. We have a id column as numeric. So we can use modular function to get randomized order:
create table #data(id numeric(10), name varchar(20))
insert #data select 209096 , 'Pharmacy'
insert #data select 204200 , 'Eyecare Center'
insert #data select 185718 , 'Duffy PC'
insert #data select 214519 , 'Shopko'
insert #data select 162225 , 'Edward Jones'
insert #data select 7609 , 'Back In Action Chiropractic Center'
select * from #data order by id % (datepart(ms, getdate()))

OK Maybe there is another way to do it just in SQL. Add a new BIT column "selected". Definitely not the fastest/best performance way to do it.
DECLARE #id INT
IF NOT EXISTS (SELECT TOP 1 id FROM customer WHERE selected = 0)
BEGIN
UPDATE customer SET selected = 0
END
SELECT #id = id FROM
(SELECT TOP 1 id, ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) AS [RandomNumber]
FROM customer WHERE selected = 0
ORDER BY [RandomNumber]) a
UPDATE customer SET selected = 1 WHERE id = #id
SELECT id, name FROM customer WHERE id = #id

Related

Add column to ensure composite key is unique

I have a table which needs to have a composite primary key based on 2 columns (Material number, Plant).
For example, this is how it is currently (note that these rows are not unique):
MATERIAL_NUMBER PLANT NUMBER
------------------ ----- ------
000000000000500672 G072 1
000000000000500672 G072 1
000000000000500672 G087 1
000000000000500672 G207 1
000000000000500672 G207 1
However, I'll need to add the additional column (NUMBER) to the composite key such that each row is unique, and it must work like this:
For each MATERIAL_NUMBER, for each PLANT, let NUMBER start at 1 and increment by 1 for each duplicate record.
This would be the desired output:
MATERIAL_NUMBER PLANT NUMBER
------------------ ----- ------
000000000000500672 G072 1
000000000000500672 G072 2
000000000000500672 G087 1
000000000000500672 G207 1
000000000000500672 G207 2
How would I go about achieving this, specifically in SQL Server?
Best Regards!
SOLVED.
See below:
SELECT MATERIAL_NUMBER, PLANT, (ROW_NUMBER() OVER (PARTITION BY MATERIAL_NUMBER, PLANT ORDER BY VALID_FROM)) as NUMBER
FROM Table_Name
Will output the table in question, with the NUMBER column properly defined
Suppose this is actual table,
create table #temp1(MATERIAL_NUMBER varchar(30),PLANT varchar(30), NUMBER int)
Suppose you want to insert only single record then,
declare #Num int
select #Num=isnull(max(number),0) from #temp1 where MATERIAL_NUMBER='000000000000500672' and PLANT='G072'
insert into #temp1 (MATERIAL_NUMBER,PLANT , NUMBER )
values ('000000000000500672','G072',#Num+1)
Suppose you want to insert bulk record.Your bulk record sample data is like
create table #temp11(MATERIAL_NUMBER varchar(30),PLANT varchar(30))
insert into #temp11 (MATERIAL_NUMBER,PLANT)values
('000000000000500672','G072')
,('000000000000500672','G072')
,('000000000000500672','G087')
,('000000000000500672','G207')
,('000000000000500672','G207')
You want to insert `#temp11` in `#temp1` maintaining number id
insert into #temp1 (MATERIAL_NUMBER,PLANT , NUMBER )
select t11.MATERIAL_NUMBER,t11.PLANT
,ROW_NUMBER()over(partition by t11.MATERIAL_NUMBER,t11.PLANT order by (select null))+isnull(maxnum,0) as Number from #temp11 t11
outer apply(select MATERIAL_NUMBER,PLANT,max(NUMBER)maxnum from #temp1 t where t.MATERIAL_NUMBER=t11.MATERIAL_NUMBER
and t.PLANT=t11.PLANT group by MATERIAL_NUMBER,PLANT) t
select * from #temp1
drop table #temp1
drop table #temp11
Main question is Why you need number column ? In mot of the cases you don't need number column,you can use ROW_NUMBER()over(partition by t11.MATERIAL_NUMBER,t11.PLANT order by (select null)) to display where you need. This will be more efficient.
Or tell the actual situation and number of rows involved where you will be needing Number column.

Merge multiple rows having some identity to a new one that have the sum of a column thats is distinct between thems

I have table like this :
id name qt
----------------
0 mm 4
1 mm 5
2 xx 8
I want update it or get new table that will produce this kind of result:
id name qt
------------------
0 mm 9 (sum of the two or multiple some identical )
1 xx 8
Including the id column will cause the GROUP BY to fail since multiple records are being summed that have different ids.
SELECT name, SUM(qt) as qt_sum
FROM table GROUP BY name
SELECT ROW_NUMBER() OVER (ORDER BY name) AS id
, name
, SUM(qt) AS qt
FROM YourTableName
GROUP BY name
ORDER BY name
I'm making the assumption that the id field doesn't actually mean anything because the id of the record xx actually changes between your two visuals. That's why I'm setting it by ROW_NUMBER() so it increments for distinct name. If this isn't the case, remove the ROW_NUMBER() expression and add id to the GROUP BY clause. This does mean that records in the name field may change depending on the number of distinct names.
If you really need and id column you could create one like this...
create table Test (id int, name varchar(10), qt int)
insert into Test values (0, 'mm', 4)
insert into Test values (1, 'mm', 5)
insert into Test values (2, 'xx', 8)
select
row_number() over (order by name) - 1
, name
, sum(qt) as qt
from Test
group by name
There may be some cases where this does not work for you, but with such limited sample data it is hard to tell.

Rotate rows into columns with column names not coming from the row

I've looked at some answers but none of them seem to be applicable to me.
Basically I have this result set:
RowNo | Id | OrderNo |
1 101 1
2 101 10
I just want to convert this to
| Id | OrderNo_0 | OrderNo_1 |
101 1 10
I know I should probably use PIVOT. But the syntax is just not clear to me.
The order numbers are always two. To make things clearer
And if you want to use PIVOT then the following works with the data provided:
declare #Orders table (RowNo int, Id int, OrderNo int)
insert into #Orders (RowNo, Id, OrderNo)
select 1, 101, 1 union all select 2, 101, 10
select Id, [1] OrderNo_0, [2] OrderNo_1
from (
select RowNo, Id, OrderNo
from #Orders
) SourceTable
pivot (
sum(OrderNo)
for RowNo in ([1],[2])
) as PivotTable
Reference: https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-2017
Note: To build each row in the result set the pivot function is grouping by the columns not begin pivoted. Therefore you need an aggregate function on the column that is being pivoted. You won't notice it in this instance because you have unique rows to start with - but if you had multiple rows with the RowNo and Id you would then find the aggregation comes into play.
As you say there are only ever two order numbers per ID, you could join the results set to itself on the ID column. For the purposes of the example below, I'm assuming your results set is merely selecting from a single Orders table, but it should be easy enough to replace this with your existing query.
SELECT o1.ID, o1.OrderNo AS [OrderNo_0], o2.OrderNo AS [OrderNo_1]
FROM Orders AS o1
INNER JOIN Orders AS o2
ON (o1.ID = o2.ID AND o1.OrderNo <> o2.OrderNo)
From your sample data, simplest you can try to use min and MAX function.
SELECT Id,min(OrderNo) OrderNo_0,MAX(OrderNo) OrderNo_1
FROM T
GROUP BY Id

A thought experiment in SQL

I want to show the number of times each distinct element in a column in a table in a SQL database appears, alongside the particular distinct element in a new output table. Is it possible in a single statement over ramming my head over it manually?
Without having actually tried, how about this:
SELECT tmp.Field, (SELECT COUNT(*) FROM [Table] t WHERE t.DesiredField = tmp.Field) AS Count
FROM
(
SELECT DISTINCT DesiredField FROM [Table]
) tmp
This would first select all distinct values from [Table] and in the outer select, take the values and the number of times they appear in the column.
You could also try
SELECT Field, SUM(1) AS Count FROM Table
GROUP BY Field
This should "flatten" the table so that it only contains distinct values in Field and the number of rows where Field has the same value.
I just tried the second - it seems to work nicely.
Turns out I was wrong all the time. The second example and the following actually return the same results:
SELECT Field, COUNT(*) AS Count FROM Table
GROUP BY Field
Simplest just to use COUNT(). You'll see varieties on what your count parameter, so here are the options.
DECLARE #tbl TABLE(id INT, data INT)
INSERT INTO #tbl VALUES (1,1),(2,1),(3,2),(4,NULL)
SELECT data
,COUNT(*) Count_star
,COUNT(id) Count_id
,COUNT(data) Count_data
,COUNT(1) Count_literal
FROM #tbl
GROUP BY data
data Count_star Count_id Count_data Count_literal
----------- ----------- ----------- ----------- -------------
NULL 1 1 0 1
1 2 2 2 2
2 1 1 1 1
Warning: Null value is eliminated by an aggregate or other SET operation.
You'll see the difference coming with the treatment of NULL if you COUNT a field that contains NULLs.

SQL Looping for repeated value for next column?

Iam trying to loop my values so that my result must look like
ETA ETD
01/01/2013 03/01/2013 //Adding Days according to condition, Here 1 day
03/01/2013 06/01/2013 //Add 3 days
06/01/2013 18/01/2013
18/01/2013 21/01/2013
Here i need to loop values so that my value is repeated in next line
For this i have done my work as
CREATE TABLE #TEMPETAETD(ROWNUM INT,ETA DATETIME,ETD DATETIME)
CREATE TABLE #TEMPETD(ID INT IDENTITY(1,1),ETD DATETIME,ROWNUM INT)
CREATE TABLE #TEMPETA(ID INT IDENTITY(1,1),ETA DATETIME,ROWNUM INT)
;WITH cte AS(
SELECT Row_Number() OVER(ORDER BY Sequence)AS RowID,#ETA AS ETA,DATEADD(DD,vd.NumHaltDays,#ETD) as ETD FROM VoyageDetails vd WHERE ID=1 and vd.Sequence BETWEEN 0 AND 1)
INSERT INTO #TEMPETAETD select * from cte
DECLARE #C INT,#C1 INT
SET #C=1
WHILE #C<(SELECT COUNT(*) FROM #TEMPETAETD)
BEGIN
INSERT INTO #TEMPETA SELECT * FROM #TEMPETAETD WHERE ROWNUM=#C
SET #C=#C+1
END
SET #C1=2
WHILE #C1<=(SELECT COUNT(*) FROM #TEMPETAETD)
BEGIN
INSERT INTO #TEMPETD SELECT * FROM #TEMPETAETD WHERE ROWNUM=#C1
SET #C1=#C1+1
END
This is my condition for Looping..., Here i could not get my repeated values coming in next row.., Can any one please help
It looks like you want values from both the current row and the row before it. In other words, you want to be able to pair up a row with the preceding row, and then select stuff from this pair.
I don't think you need loops for this. Looping is generally pretty slow.
The general idea is, like you did, number the rows. Then you can join the table to itself with the number. Below is an example of how you can do this pairing without using a loop. Schema:
create table T (a int);
insert into T values
(1), (7), (20), (30), (500), (800), (1300), (2112);
query:
with tNumbered as (
select row_number() over (order by a) as rowID, a
from T
)
select tLeft.a as l, tRight.a as r from tNumbered tLeft
left join tNumbered tRight on tLeft.rowID = tRight.rowID -1
Here's a fiddle showing it in action: http://sqlfiddle.com/#!3/a257a/2