Concatenate two colums in one in SQL - tsql

I have two columns, on of them is a foreign ID, how can I concatenate them into one column?
example:
StateID = 1
Area = "Bronx"
To become:
New York - Bronx
Edit:
Table1 = [Address] has two columns, (ID, Name)
Table2 = [Requests] has many columns including (Area, StateID)

Use + to concatenate columns:
SELECT a.Name + ' - ' + r.Area As StateAndArea
FROM dbo.Requests r INNER JOIN dbo.Address a
ON r.StateID = a.ID
ORDER BY StateAndArea -- ( alias can be used in order by but not in where )
+ (String Concatenation)

SELECT StateID + ' - ' + Area AS SateArea

Related

How to use redshift regex to get out numbers in an array

In redshift, I have a column that contains an array-like string like [1,2,3] and I want to return 1,2,3 using Redshift's regex functionality. How can one do this? I don't want to do this:
SELECT LISTAGG(option_name , ',') WITHIN GROUP (ORDER BY option_name) as pets_names
FROM reference.vital_options
WHERE option_id in
(
-- this nested CTE splits the json string array into comma separated pet ids
with NS AS (
SELECT vo.option_id + 1 as n
FROM <column with number id> as vo
WHERE upper(vo.country) = 'US'
...
)
select TRIM(JSON_EXTRACT_ARRAY_ELEMENT_TEXT(u.pets_vital, NS.n - 1)) AS val
FROM NS
INNER JOIN go_prod.users AS u ON NS.n <= JSON_ARRAY_LENGTH(u.pets_vital)
WHERE u.id = %(user_id)s
)
AND ...
Is all you are trying to do is remove the square brackets? If so then the translate() function is likely what you want to use. For example:
create table test as (select '[1,2,3]'::text as A);
select a, translate(a, '][', '') as b from test;

T-SQL - Insert new row into table from a select of a group of four rows

I am logging the filters that users select on my web application and need to create a new row which shows what group of filters they have selected.
Due to way in which the filters are logged in the table they come in groups of four which can be seen in screenshot below:
Based on these groups of four I need to Insert a new row that contains a comma separated string into the Message field of the value(s) after the : symbol.
seems like there is no identifier that would group the four rows together (can't see full timestamp in your sample). here is an example with a grouping column that's computed based on mod 4 and recursive cte
DECLARE #tab TABLE (id int identity(1,1), msg varchar(100))
INSERT INTO #tab
VALUES
('selected: a')
,('selected: b')
,('selected: c')
,('selected: d')
,('selected: e')
,('selected: f')
,('selected: g')
,('selected: h')
,('selected: i')
,('selected: j')
,('selected: k')
,('selected: l')
;with src --add grouping column
as
(
SELECT
id
,msg = left(msg, charindex(':', msg, 1)-1)
,val = LTRIM(SUBSTRING(msg, CHARINDEX(':', msg, 1)+1, len(msg) ))
,nid = ROW_NUMBER() over (partition by id % 4 order by id)
FROM #tab
)
,source --add column for recursion
as
(
SELECT
*,
rn = ROW_NUMBER() OVER (PARTITION BY nid ORDER BY id)
FROM src
)
,rcdef -- define recursive cte
AS (
SELECT
nid
,msg
,val = convert(varchar(max), val)
,rn = 1
FROM source
WHERE rn = 1
UNION ALL
SELECT
rcdef.nid
, rcdef.msg
,val = convert(varchar(max), rcdef.val +',' + source.val) --concatenate vals
,rn = rcdef.rn + 1
FROM rcdef
INNER JOIN source on source.nid = rcdef.nid and source.rn = rcdef.rn + 1
)
SELECT
nid,
val = msg + ': ' + max(val)
FROM rcdef
GROUP BY nid, msg

Remove characters from concatenation

I have a table in with the following layout:
CREATE TABLE dbo.tbl (
Ten_Ref VARCHAR(20) NOT NULL,
Benefit VARCHAR(20) NOT NULL
);
INSERT INTO dbo.tbl (Ten_Ref, Benefit)
VALUES ('1', 'HB'),
('1', 'WTC'),
('1', 'CB'),
('2', 'CB'),
('2', 'HB'),
('3', 'WTC');
I then run this code to perform a transform and concatenation (I need all the benefit information in one field'
with [pivot] as
(
SELECT Ten_Ref
,[HB] = (Select Benefit FROM tbl WHERE t.Ten_Ref = Ten_Ref and Benefit = 'HB')
,[CB] = (Select Benefit FROM tbl WHERE t.Ten_Ref = Ten_Ref and Benefit = 'CB')
,[WTC] = (Select Benefit FROM tbl WHERE t.Ten_Ref = Ten_Ref and Benefit = 'WTC')
/*Plus 7 more of these*/
FROM tbl as t
GROUP BY Ten_Ref
)
select p.ten_Ref
/*A concatenation to put them all in one field, only problem is you end up with loads of spare commas*/
,[String] = isnull (p.HB,0) + ',' + isnull (p.cb,'') + ',' + isnull (p.wtc,'')
from [pivot] as p
My problem is not every ten_ref has all of the Benefits attached.
Using this code, where there is a gap or NULL then I end up with loads of double commas e.g 'HB,,WTC'
How can I get it so it is only one comma, regardless of the amount of benefits each tenancy has?
Are you looking for something like this?
SELECT A.Ten_Ref,
STUFF(CA.list,1,1,'') list
FROM tbl A
CROSS APPLY(
SELECT ',' + Benefit
FROM tbl B
WHERE A.Ten_Ref = B.Ten_Ref
ORDER BY Benefit
FOR XML PATH('')
) CA(list)
GROUP BY A.ten_ref,CA.list
Results:
Ten_Ref list
-------------------- ------------------
1 CB,HB,WTC
2 CB,HB
3 WTC
Or if you really want to use pivot and manually concatenate, you could do this:
SELECT Ten_Ref,
--pvt.*,
ISNULL(HB + ',','') + ISNULL(CB + ',','') + ISNULL(WTC + ',','') AS list
FROM tbl
PIVOT
(
MAX(Benefit) FOR Benefit IN([HB],[CB],[WTC])
) pvt

Get index of row within a group?

I have two tables:
Unit:
UnitId int PK
Title varchar
UnitOption:
UnitOptionId int PK
UnitId int FK
Title varchar
Quote:
QuoteId int PK
UnitOptionId int FK
Title varchar
I want to create a scalar UDF that takes a QuoteId param and returns a varchar that contains the following description (pseudu):
Quote.Title + '-' + Unit.Title + '-' + Unit.UnitId +
/* Here is where my question is:
If there are more than 1 UnitOption under this Unit, then
return '-' + the UnitOption number under this Unit
(i.e.) if under this Unit, there are 3 UnitOption with IDs 13, 17, 55
under the unit, and the current Quote.UnitOptionId is the 17 one,
it should return 2.
Which means I want to retrieve an ID of this row in the group.
Else
return ''
*/
If you're using SQL 2005 or later and I've interpreted your question correctly, you should be able to adapt the following into your function.
WITH [UnitExt] AS
(
SELECT
[Unit].[UnitId],
[Unit].[Title],
COUNT(*) AS [Count]
FROM [Unit]
INNER JOIN [UnitOption] ON [UnitOption].[UnitId] = [Unit].[UnitId]
GROUP BY
[Unit].[UnitId],
[Unit].[Title]
)
SELECT
[Quote].[Title] + '-' + [UnitExt].[Title] + '-' + [UnitExt].[UnitId] +
CASE
WHEN [UnitExt].[Count] > 1 THEN '-' +
CAST([UnitOption].[UnitOptionId] AS varchar(max))
ELSE ''
END
FROM [Quote]
INNER JOIN [UnitOption] ON [UnitOption].[UnitOptionId] =
[Quote].[UnitOptionId]
INNER JOIN [UnitExt] ON [UnitExt].[UnitId] = [UnitOption].[UnitId]
WHERE [Quote].[QuoteId] = #QuoteId
Something like this should do it.
SELECT DISTINCT Quote.Title +
' - ' + Unit.Title +
' - ' + Unit.UnitId +
CASE
WHEN COUNT(*) OVER(PARTITION BY Quote.Id) > 0
THEN
' - ' + CAST(ROW_NUMBER() OVER (PARTITION BY Quote.Id ORDER BY Quote.UnitOptionId) AS varchar)
ELSE
''
END
FROM Quote
JOIN UnitOption ON UnitOption.Id = Quote.UnitOptionId
JOIN Unit ON Unit.Id = UnitOption.UnitId
WHERE Quote.Id = #QuoteId
CREATE FUNCTION ufnGetDescription
(#QuoteID INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #RetVal VARCHAR(MAX);
WITH CurRow
AS (SELECT quote.title + '- ' + unit.title AS start,
u.unitid,
quoteid,
uo.unitoptionid
FROM quote
INNER JOIN unitoption uo
ON quote.unitoptionid = uo.unitoptionid
INNER JOIN unit
ON uo.unitid = unit.unitid
WHERE quote.quoteid = #QuoteID),
AllUnits
AS (SELECT u.unitid,
uo.unitoptionid,
Row_number()
OVER(PARTITION BY u.unitid ORDER BY uo.unitoptionid) AS NUMBER,
Count(* )
OVER(PARTITION BY u.unitid ) AS cntUnits
FROM unit
INNER JOIN unionoption uo
ON unit.unitid = uo.unitid
WHERE u.unitid IN (SELECT unitid
FROM CurRow))
SELECT #RetVal = CASE
WHEN a.cntUnits = 1 THEN ''
ELSE r.start + '-' + Cast(NUMBER AS VARCHAR(max))
END
FROM AllUnits a
INNER JOIN CurRow r
ON a.unitoptionid = r.unitoptionid
RETURN #RetVal
END

Difficult query (DB2)

Suppose I have a table called spitems with the following fields:
spitemid (unique key)
modifiedon (timestamp)
parentid
a number of other unsignificant fields
What I want to retrieve, is the spitem rows with the highest modifiedon day for each parentid.
However, be aware that the modifiedon timestamp is not unique, so it is possible that for one parent id, there are two spitemids with the same modifiedon timestamp. In that case, I need one of these two spitemids listed, I don't care which one.
So to be clear: the list I return should contain all the parentids once and only once.
update
meeting over, here is my shot:
select *
from table
join where spitmid in
(select max(spitmid)
from table
join
(select parentid, max(modifiedon) as d from table group by parentid) inlist
on table.parentid = inlist.parentid and table.modifiedon = inlist.d
group by parentid, datemodified
)
old entry
not sure if this is different on DB2, here it is for sql server.
select *
from table
join (select parentid, max(modifiedon) as d from table group by parentid) as toplist on
table.parentid = toplist.parentid and table.modifiedon = toplist.d
hmm... this will return more than one for the dups... can't fix it now, have to go to a meeting.
Based on your requirements, following should get you the latest items.
SELECT t1.*
FROM Table t1
INNER JOIN (
SELECT spitemid = MAX(t1.spitemid)
FROM Table t1
INNER JOIN (
SELECT parentid, modifiedon = MAX(modifiedon)
FROM Table
GROUP BY parentid
) t2 ON t2.parentid = t1.parentid
AND t2.modifiedon = t1.modifiedon
GROUP BY t1.parentid, t1.modifiedon
) t2 ON t2.spitemid = t1.spitemid
You can do it with two nested subqueries. The first gets max modifiedon for each parentid, and then the second gets max spitemid for each parentid/modifiedon group.
SELECT *
FROM spitems
WHERE spitemid IN
(
SELECT parentid, modifiedon, max(spitemid) spitemid
FROM (
SELECT parentid, MAX(modifiedon) modifiedon
FROM spitems
GROUP BY parentid
) A
GROUP BY parentid, modifiedon
)
A common table expression will give you the opportunity to number the rows before you issue the final SELECT.
WITH items AS
(
SELECT spitemid, parentid, modifiedon,
ROWNUMBER() OVER (PARTITION BY parentid ORDER BY modifiedon DESC) AS rnum
FROM yourTable
)
SELECT spitemid, parentid, modifiedon FROM items WHERE rnum = 1
;
SELECT sr.receiving_id, sc.collection_id FROM stock_collection as sc, stock_requisation as srq, stock_receiving as sr WHERE (sc.stock_id = '" & strStockID & "' AND sc.datemm_issued = '" & strMM & "' AND sc.qty_issued >= 0 AND sc.collection_id = srq.requisition_id AND srq.active_status = 'Active') OR (sr.stock_id = '" & strStockID & "' AND sr.datemm_received = '" & strMM & "' AND sr.qty_received >= 0)