SQL Server - Generate the same random number into multiple columns - sql-server

I would like to generate a random number (5 or 6 digits) but not just into one column, in 4 actually.
ID1 ID2 Type LotNumber ID3 ID4
-------------------------------------------------------------
721 721 1 Lot1 721 721
721 721 1 Lot1 721 721
Looking over the internet and several articles, mostly generate a random number to be used in just one column and that's it. Is there any way I can achieve this using SQL? Thanks
EDIT
I used this statement:
SELECT FLOOR(RAND(CHECKSUM(NEWID()))*(99999-10000+1)+1000) AS ID
VIEW
CREATE VIEW MyView
AS
SELECT
'' AS ID1,
'' AS ID2,
CASE WHEN t.fADTableField4Code='Aggregated' THEN CAST(1 AS BIT) ELSE CAST(2 AS BIT) END AS Type,
ISNULL(t.fADTableField3Code, '') AS LotNumber,
'' AS ID3,
'' AS ID4
FROM MyTable AS t
GO
XML File
The XML file has to look like this:
<Documents>
<Document>
<ID1>721</ID1>
<ID2>721</ID2>
<Type>1</Type>
<LotNumber>Lot1</LotNumber>
<ID3>721</ID3>
<Date>2018-12-04</Date>
<Details>
<Detail>
<ID4>721</ID4>
............
</Details>
</Document>

Try this and expand upon it.
select a.*
, b.id as ID1, b.id as ID2 --Get ID from applied table and use as often as you need
from (select 1) as a(ID) -- this is your main table
cross apply (SELECT FLOOR(RAND(CHECKSUM(NEWID()))*(99999-10000+1)+1000) AS ID) B

you can use either a CTE or a subquery
SELECT
ID1 = R.ID
,ID2 = R.ID
,ID3 = R.ID
,ID4 = R.ID
FROM
(SELECT
FLOOR(RAND(CHECKSUM(NEWID()))*(99999-10000+1)+1000)
AS ID
) R
;WITH R
AS
(SELECT
FLOOR(RAND(CHECKSUM(NEWID()))*(99999-10000+1)+1000)
AS ID
)
SELECT
ID1 = R.ID
,ID2 = R.ID
,ID3 = R.ID
,ID4 = R.ID
FROM R

Related

Create a stored procedure to aggregate rows

Having a transaction table with the following rows:
Id UserId PlatformId TransactionTypeId
-------------------------------------------------
0 1 3 1
1 1 1 2
2 2 3 2
3 3 2 1
4 2 3 1
How do I write a stored procedure that can aggregate the rows into a new table with the following format?
Id UserId Platforms TransactionTypeId
-------------------------------------------------
0 1 {"p3":1,"p1":1} {"t1":1,"t2":1}
1 2 {"p3":2} {"t2":1,"t1":1}
3 3 {"p2":1} {"t1":1}
So the rows are gouped by User, count each platform/transactionType and store as key/value json string.
Ref: My previous related question
You could use GROUP BY and FOR JSON:
SELECT MIN(ID) AS ID, UserId, MIN(sub.x) AS Platforms, MIN(sub2.x) AS Transactions
FROM tab t
OUTER APPLY (SELECT CONCAT('p', platformId) AS platform, cnt
FROM (SELECT PlatformId, COUNT(*) AS cnt
FROM tab t2 WHERE t2.UserId = t.UserId
GROUP BY PlatformId) s
FOR JSON AUTO) sub(x)
OUTER APPLY (SELECT CONCAT('t', TransactiontypeId) AS Transactions, cnt
FROM (SELECT TransactiontypeId, COUNT(*) AS cnt
FROM tab t2 WHERE t2.UserId = t.UserId
GROUP BY TransactiontypeId) s
FOR JSON AUTO) sub2(x)
GROUP BY UserId;
DBFiddle Demo
Result is a bit different(array of key-value) but please treat it as starting point.
Your sample JSON is not really a json, but since you want it that way:
SELECT u.UserId, plt.pValue, ttyp.ttValue
FROM Users AS [u]
CROSS APPLY (
SELECT '{'+STUFF( (SELECT ',"'+pn.pName+'":'+LTRIM(STR(pn.pCount))
FROM (SELECT p.Name AS pName, COUNT(*) AS pCount
FROM transactions t
left JOIN Platforms p ON p.PlatformID = t.PlatformId
WHERE t.UserId = u.UserId
GROUP BY p.PlatformId, p.Name
) pn
FOR XML PATH('')),1,1,'')+'}'
) plt(pValue)
CROSS APPLY (
SELECT '{'+STUFF( (SELECT ',"'+tty.ttName+'":'+LTRIM(STR(tty.ttCount))
FROM (SELECT tt.Name AS ttName, COUNT(*) AS ttCount
FROM transactions t
left JOIN dbo.TransactionType tt ON tt.TransactionTypeId = t.TransactionTypeID
WHERE t.UserId = u.UserId
GROUP BY tt.TransactionTypeId, tt.Name
) tty
FOR XML PATH('')),1,1,'')+'}'
) ttyp(ttValue)
WHERE EXISTS (SELECT * FROM transactions t WHERE u.UserId = t.UserId)
ORDER BY UserId;
DBFiddle Sample

How to merge list from SQL Server stored procedure

ALTER PROCEDURE [dbo].[spGetItemCategories]
AS
BEGIN
SET NOCOUNT ON;
--SELECT * FROM ItemCategories
SELECT
IC.Id, IC.Name ,C.Id AS CompanyId, C.Name AS CompanName
FROM
ItemCategories IC
JOIN
CompanyItems CI ON IC.Id = CI.ItemCategoryId
JOIN
Companies C ON CI.CompanyId = C.Id
--WHERE CI.CompanyId IN (SELECT TOP(100)* FROM Companies C)
END
This displays data like:
4 sdfs 14 Nestle
4 sdfs 15 Unilever
but I want to get like this:
4 sdfs 14 Nestle
15 Unilever
You can check this method but the same data.
declare #mytable table (compid int,compname varchar(20),itemid int, itemdesc varchar(20))
insert into #mytable
values
(1,'Company A',100,'Nestle'),
(1,'Company A',200,'UniLever'),
(2,'Company B',300,'Citrix'),
(2,'Company B',400,'SQL'),
(2,'Company B',500,'Oracle'),
(1,'Company B',600,'Microsoft')
select
iif(left(m1.ord_id,1)>1,NULL,m.compid) [CompID],
iif(left(m1.ord_id,1)>1,NULL,m.compname) [CompName],
m.itemid,
m.itemdesc
from #mytable m
inner join (
select distinct compid,row_number() over (partition by compid order by itemid) [ord_id], itemid
from #mytable) m1
on m.compid = m1.compid and m.itemid = m1.itemid
or CTE
;with cte as
(
select distinct compid,row_number() over (partition by compid order by itemid) [ord_id], itemid
from #mytable
)
select
iif(left(m1.ord_id,1)>1,NULL,m.compid) [CompID],
iif(left(m1.ord_id,1)>1,NULL,m.compname) [CompName],
m.itemid,
m.itemdesc
from #mytable m
inner join cte m1
on m.compid = m1.compid and m.itemid = m1.itemid
if you are not happy with nulls replace the fields
iif(left(m1.ord_id,1)>1,'',cast(m.compid as varchar)) [CompID],
iif(left(m1.ord_id,1)>1,'',m.compname) [CompName],
Result
CompID CompName itemid itemdesc
1 Company A 100 Nestle
200 UniLever
600 Microsoft
2 Company B 300 Citrix
400 SQL
500 Oracle

Select row with Distinct max(column value)

[ExactReplica].[FilteredOpportunityProduct] Table
Opportunityid baseamount
1 500
1 500
2 600
2 700
[ExactReplica].FilteredOpportunity Table
Opportunityid name
1 ABC
2 CDF
I want to take the maximum baseamount; however, am facing issue when there exists duplicate of the baseamount, how can I take only one record
My Query
select
MaxAmount.[baseamount] ,
c.name
FROM [ExactReplica].FilteredOpportunity c
Left JOIN
(
SELECT opportunityid,
MAX((baseamount)) baseamount
FROM [ExactReplica].[FilteredOpportunityProduct]
GROUP BY opportunityid
) MaxAmount ON c.opportunityid = MaxAmount.opportunityid
inner JOIN
[ExactReplica].[FilteredOpportunityProduct] p ON MaxAmount.opportunityid = p.opportunityid
AND MaxAmount.baseamount = p.baseamount
Try this:
select max(baseamount) baseamount,a.name
from
(select
baseamount, ROW_NUMBER() over (partition by p.opportunityid,baseamount order by p.baseamount desc) rn,
c.name
FROM FilteredOpportunity c
inner JOIN
[FilteredOpportunityProduct] p ON c.opportunityid = p.opportunityid) a
where rn=1
group by a.name
OUTPUT:
baseamount name
500 ABC
700 CDF
Can you try below query for expected result, I have executed the below scripts :
For Table Creation :
CREATE TABLE FILTEREDOPPORTUNITYPRODUCT (
OPPORTUNITYID INT NULL,
BASEAMOUNT VARCHAR(24) NULL
)
CREATE TABLE FILTEREDOPPORTUNITY (
OPPORTUNITYID INT NULL,
NAME VARCHAR(24) NULL
)
Insertion:
INSERT INTO FILTEREDOPPORTUNITYPRODUCT (OPPORTUNITYID,BASEAMOUNT) VALUES
(1,500),(1,500),(2,600),(2,700)
INSERT INTO FILTEREDOPPORTUNITY (OPPORTUNITYID,NAME) VALUES
(1,'ABC'),(2,'CDF')
Selection:
SELECT
A.OPPORTUNITYID,B.NAME,MAX(BASEAMOUNT) AS BASEAMOUNT
FROM FILTEREDOPPORTUNITYPRODUCT AS A
JOIN FILTEREDOPPORTUNITY AS B
ON A.OPPORTUNITYID = B.OPPORTUNITYID
GROUP BY A.OPPORTUNITYID,B.NAME

Rewriting function to conditional CTE

Considering following table:
SELECT [ItemID]
,[ParentID]
,[PolicyID]
,[PolicyRoot]
FROM [AdventureWorks2008R2].[dbo].[Example]
ItemID ParentID PolicyID PolicyRoot
----------- ----------- ---------- ----------
1 NULL default 1
2 1 b 1
3 1 c 0
4 NULL d 1
5 3 e 0
6 3 f 1
7 NULL g 0
I'm trying to select the PolicyID from each item where PolicyRoot = 1, in case PolicyRoot = 0 I need to use PolicyID from its ParentID. This is recursive...
Working with a function:
CREATE FUNCTION dbo.Policies(#ItemID INT) RETURNS VARCHAR(10)
AS
BEGIN
DECLARE #ParentID INT, #PolicyRoot BIT, #PolicyID VARCHAR(10)
SELECT #ParentID = ParentID
, #PolicyRoot = PolicyRoot
, #PolicyID = PolicyID
FROM [dbo].[Example]
WHERE ItemID = #ItemID
IF #PolicyRoot != 1
SELECT #PolicyID = dbo.Policies(#ParentID)
RETURN #PolicyID
END;
GO
SELECT ItemID
, dbo.Policies(ItemID) AS Policy
FROM [dbo].[Example];
ItemID Policy
----------- ----------
1 default
2 b
3 default
4 d
5 default
6 f
7 NULL
I'm trying to rewrite this function to a CTE, but I don't have any CTE knowledge yet. I've read into multiple CTE's but I don't have a single clue how to manage a conditional CTE. This is as far as I've gotten, I'm not familiar (enough) with the UNION ALL.
WITH Policies (ItemID, PolicyID) AS (
SELECT ItemID
, PolicyID
FROM dbo.Example
UNION ALL
...
)
SELECT ItemID
, PolicyID
FROM Policies;
Can someone explain me in plain steps how such a CTE works and push me in the right direction?
A recursive CTE works by joining to itself, using a UNION ALL to collate the results.
You start with yourtable to populate the initial dataset of the recursive query
select * from yourtable
and you add to that with the UNION ALL, further results
select c.ItemID, t2.ParentID, t2.PolicyID, t2.PolicyRoot
from yourtable t2
inner join c on c.ParentID = t2.ItemID
where c.PolicyRoot=0
and the recursion occurs in this - where the results of this query are fed through this query again and again, up to the MAXRECURSION limit, or when no more results are added.
;with c as
(
select * from yourtable
union all
select c.ItemID, t2.ParentID, t2.PolicyID, t2.PolicyRoot
from yourtable t2
inner join c on c.ParentID = t2.ItemID
where c.PolicyRoot=0
)
select t.ItemID, c.PolicyID
from yourtable t
left join c on t.ItemID = c.ItemID
and c.PolicyRoot=1

Combining multiple records into one

I'm using the following query:
DECLARE #Code varchar(6)
SELECT a.Code, a.Description, a.Time, b.id
FROM TableA a
LEFT OUTER JOIN TableB B ON a.id = b.id
WHERE a.Code = #Code
The issue I'm having is it's returning multiple records because of the outer join, something like the following:
Code Description Time B.id
5038 sample desc 4 108
5038 sample desc 4 632
5038 sample desc 4 633
5038 sample desc 4 197
5038 sample desc 4 503
What would be the best way to combine these into one record, with say a delimited list of b.id's?
For a delimited list you can go for XML Path clause. Here is the explanation: http://blog.sqlauthority.com/2013/04/05/sql-server-group-by-rows-and-columns-using-xml-path-efficient-concating-trick/
You can use this method found here
USE AdventureWorks
GO
DECLARE #listStr VARCHAR(MAX)
SELECT #listStr = COALESCE(#listStr+',' ,'') + Name
FROM Production.Product
SELECT #listStr
GO

Resources