Can you concat with a space-space - concatenation

I have looked at several of the concat questions and can't seem to make those solutions work for me.
case "tblContestant":
$sql = "SELECT e.id as Id,#n := #n + 1 n, replace(c.name, ',', ' ') as name, c.address, NULL, c.city, c.state, c.phonenumber, c.email, c.sanctionbody, concat(c.id,c.sanctionnumber) as sanctionnumber, mcrc.amount, c.zip, c.jrboater
FROM contestants c
LEFT JOIN main_contestant_register_class mcrc ON mcrc.contestant_id = c.id
LEFT JOIN events e ON e.id = mcrc.event_id, (SELECT #n := 0) m
WHERE e.id = $id";
The above gives me the result of combining c.id with c.sanctionnumber (142155) however I would like a space-space between c.id and c.sanctionnumber
(14 - 2155) or (14-2155) if spaces are not an option.
Thanks in advance!

case "tblContestant":
$sql = "SELECT e.id as Id,#n := #n + 1 n, replace(c.name, ',', ' ') as name, c.address, NULL, c.city, c.state, c.phonenumber, c.email, c.sanctionbody, concat(c.id,' - '+ c.sanctionnumber) as sanctionnumber, mcrc.amount, c.zip, c.jrboater
FROM contestants c
LEFT JOIN main_contestant_register_class mcrc ON mcrc.contestant_id = c.id
LEFT JOIN events e ON e.id = mcrc.event_id, (SELECT #n := 0) m
WHERE e.id = $id";

Avi thanks for your help the issue is resolved! I simply changed the + to a , and it is now giving me the desired results.
concat(c.id,' - '+ c.sanctionnumber) as sanctionnumber, gives me 142155
concat(c.id,' - ', c.sanctionnumber) as sanctionnumber, gives me 14 - 2155

Related

Sub query with multiple result

I'm working with Sql Server, I have written one query.when i'm executing that query getting following error.
Error:
"Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
SELECT b.booking_id,b.booking_ref,b.destination,b.room_format,b.checkin,b.checkout,b.booking_status,b.currency,b.rooms,b.booking_date,
b.adults,b.childs,b.seniors,b.youth,b.child2,b.booking_type,
pb.amount_charged,pb.original_total_cost 'total_amount',b.special_request,b.cancelled_date,b.emergency_contact,b.emergency_email,
(SELECT TOP 2 CAST(isbreakfast AS VARCHAR(10)) + '_' + room_desc FROM tbl_hotel_room_booking WHERE pb.product_booking_id = product_booking_id) 'room_desc',
tba.traveller_address1,tba.traveller_address2,tba.traveller_city,
tba.traveller_state,tba.traveller_country,tba.traveller_zip_code,
th.transaction_amount,th.reversal_amount,th.branch_id,th.agent_id,th.transaction_type,
pb.product_booking_id,pb.product_status,pb.provider_confirmation_code,pb.booking_source,pb.product_name,pb.product_type,pb.product_id,
tft.ticket,
(SELECT TOP 1 as_of_date + '_' + hotel_penalty FROM tbl_hotel_room_cancellation WHERE booking_id='0BCE1ABC-EA42-4030-A9F1-CA8D176825C0') 'as_of_date',
tpd.adult_price,tpd.cost_currency,tpd.sell_currency,tpd.booking_fee,tpd.taxes,tpd.exchange_rate,tpd.subagency_markup_val,
tpd.charged_amount,tpd.child_price,tpd.senior_price,tpd.youth_price, tpd.actual_price,(ISNULL(tpd.markup_total,0) + ISNULL(tpd.subagency_markup_val,0)) 'markup_total', tpd.markup_total 'agency_markup'
FROM tbl_booking b
INNER JOIN tbl_product_booking pb ON b.booking_id = pb.booking_id
LEFT JOIN tbl_transaction_history th ON b.booking_ref = th.reference_number
LEFT JOIN tbl_traveller_billing_address tba ON b.booking_id = tba.booking_id
LEFT JOIN tbl_purchasedproduct_details tpd ON b.booking_id = tpd.booking_id
LEFT JOIN tbl_flight_tickets tft ON b.booking_id = tft.booking_id
WHERE b.booking_id = '0BCE1ABC-EA42-4030-A9F1-CA8D176825C0'
AND (th.transaction_type IS NULL OR LOWER(th.transaction_type) = 'booking' OR LOWER(th.transaction_type) = 'creditcardbooking' OR Lower(th.transaction_type) = 'manualbooking')
Finally i know why i'm getting this error..I'm trying to return multiple result from sub query..
(SELECT TOP 2 CAST(isbreakfast AS VARCHAR(10)) + '_' + room_desc FROM tbl_hotel_room_booking WHERE pb.product_booking_id = product_booking_id) 'room_desc',
can any one help how can i return multiple result here.
If you basically left join your query with that table and set filter for top 2 records i think you will get what you want.
SELECT
b.booking_id,
b.booking_ref,
b.destination,
b.room_format,
b.checkin,
b.checkout,
b.booking_status,
b.currency,
b.rooms,
b.booking_date,
b.adults,
b.childs,
b.seniors,
b.youth,
b.child2,
b.booking_type,
pb.amount_charged,
pb.original_total_cost 'total_amount',
b.special_request,
b.cancelled_date,
b.emergency_contact,
b.emergency_email,
CAST(brb.isbreakfast AS VARCHAR(10)) + '_' + brb.room_desc AS 'room_desc'
tba.traveller_address1,
tba.traveller_address2,
tba.traveller_city,
tba.traveller_state,
tba.traveller_country,
tba.traveller_zip_code,
th.transaction_amount,
th.reversal_amount,
th.branch_id,
th.agent_id,
th.transaction_type,
pb.product_booking_id,
pb.product_status,
pb.provider_confirmation_code,
pb.booking_source,
pb.product_name,
pb.product_type,
pb.product_id,
tft.ticket
(SELECT TOP 1 as_of_date + '_' + hotel_penalty FROM tbl_hotel_room_cancellation WHERE booking_id='0BCE1ABC-EA42-4030-A9F1-CA8D176825C0') 'as_of_date',
tpd.adult_price,tpd.cost_currency,tpd.sell_currency,tpd.booking_fee,tpd.taxes,tpd.exchange_rate,tpd.subagency_markup_val,
tpd.charged_amount,tpd.child_price,tpd.senior_price,tpd.youth_price, tpd.actual_price,(ISNULL(tpd.markup_total,0) + ISNULL(tpd.subagency_markup_val,0)) 'markup_total', tpd.markup_total 'agency_markup'
FROM tbl_booking b
INNER JOIN tbl_product_booking pb ON b.booking_id = pb.booking_id
LEFT JOIN tbl_hotel_room_booking brb ON pb.product_booking_id = brb.product_booking_id
LEFT JOIN tbl_transaction_history th ON b.booking_ref = th.reference_number
LEFT JOIN tbl_traveller_billing_address tba ON b.booking_id = tba.booking_id
LEFT JOIN tbl_purchasedproduct_details tpd ON b.booking_id = tpd.booking_id
LEFT JOIN tbl_flight_tickets tft ON b.booking_id = tft.booking_id
WHERE b.booking_id = '0BCE1ABC-EA42-4030-A9F1-CA8D176825C0'
AND brb.isbreakfast IN (Select Top 2 IsBreakfast
FROM tbl_hotel_room_booking)
AND (th.transaction_type IS NULL
OR LOWER(th.transaction_type) = 'booking'
OR LOWER(th.transaction_type) = 'creditcardbooking' OR Lower(th.transaction_type) = 'manualbooking')

Getting a max date using various groups in a select in SQL Server

Been stuck on this. I have the query and the result set below:
DECLARE #bookdate date = cast(DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), - 1) AS DATE)
DECLARE #offset int = 1
SELECT distinct #bookdate BookDate
,th.Transactioncd TransactionType
,bp.PolicyNumber PolicyNumber
,cast(bp.EffectiveDt AS DATE) EffectiveDate
,cast(th.TransactionEffectiveDt AS DATE) TransactionEffectiveDate
,NULL
,th.TransactionNumber TransactionNumber
,cast(bp.ExpirationDt AS DATE) ExpirationDate
,UPPER(ni.IndexName) InsuredName
,isnull(UPPER(ad.Addr1), '') + ' ' + isnull(UPPER(ad.Addr2), '') + ' ' + isnull(UPPER(ad.Addr3), '') + ' ' + isnull(UPPER(ad.Addr4), '') InsuredStreetAddress
,UPPER(ad.City) InsuredCity
,UPPER(ad.StateProvCd) InsuredState
,ad.PostalCode InsuredZipCode
,i.EntityTypeCd InsuredType
,isnull(tr.ReasonCd, '') ReasonCode
,cast(datediff(mm, th.transactioneffectivedt, bp.expirationdt) / cast(datediff(mm, bp.effectivedt, bp.expirationdt) AS DECIMAL(15, 4)) AS DECIMAL(15, 4)) ProrateFactor
,'0'
,'0'
,'0'
,bd.YearBuilt YrConstruction
,ln.PROPDed + '%' [% loss ded EQ]
,CAST(bd.BldgNumber AS VARCHAR(255)) BldgNumber
,CONVERT(INT,REPLACE(bd.BuildingValue,',','')) BuildingValue
,CONVERT(INT,REPLACE(bd.ContentsBLimit,',','')) ContentsBLimit
,CONVERT(INT,REPLACE(bd.ContentsCLimit,',','')) ContentsCLimit
,CONVERT(INT,REPLACE(bd.TIBLimit,',','')) TIBLimit
,CONVERT(INT,REPLACE(bd.BILimit,',','')) BILimit
,CONVERT(INT,REPLACE(bd.EDPLimit,',','')) EDPLimit
FROM java.basicpolicy bp
INNER JOIN java.nameinfo ni ON ni.SystemId = bp.SystemId
AND ni.CMMContainer = bp.CMMContainer
INNER JOIN java.partyinfo pti on pti.Id=ni.ParentId
AND pti.CMMContainer=bp.CMMContainer
and pti.SystemId=bp.SystemId
INNER JOIN java.line ln ON ln.CMMContainer = bp.CMMContainer
AND bp.SystemId = ln.SystemId
INNER JOIN java.risk r on r.SystemId=bp.SystemId
AND r.CMMContainer=bp.CMMContainer
AND r.ParentId=ln.Id
INNER JOIN java.building bd ON bd.CMMContainer = bp.CMMContainer
AND bd.SystemId = bp.SystemId
AND bd.ParentId=r.id
AND bd.[Status] = 'ACTIVE'
INNER JOIN java.addr ad ON ad.CMMContainer = ni.CMMContainer
AND bp.SystemId = ad.SystemId
AND ad.AddrTypeCd in ('RiskAddr')
AND ad.ParentId = bd.id
INNER JOIN java.transactioninfo th ON th.CMMContainer = bp.CMMContainer
AND th.SystemId = bp.SystemId
LEFT JOIN java.transactionreason tr ON tr.CMMContainer = bp.CMMContainer
AND TR.SystemId = bp.SystemId
AND TR.ParentId = th.ID
INNER JOIN java.insured i ON i.CMMContainer = bp.CMMContainer
AND i.SystemId = bp.SystemId
WHERE bp.CMMContainer = 'Application'
AND ni.NameTypeCd = 'INSUREDNAME'
AND (
th.TransactionCd IN (
'new business'
,'endorsement'
,'cancellation'
,'rewrite-new'
)
OR (
th.WrittenPremiumAmt IS NOT NULL
AND th.WrittenPremiumAmt <> 0
AND th.TransactionCd IN ('reinstatement')
)
)
AND bp.CarrierCd = 'ENIC'
AND th.TransactionEffectiveDt not like '2016-12%'
GROUP BY
th.Transactioncd
,bp.PolicyNumber
,cast(bp.EffectiveDt AS DATE)
,cast(th.TransactionEffectiveDt AS DATE)
,th.TransactionNumber
,cast(bp.ExpirationDt AS DATE)
,UPPER(ni.IndexName)
,isnull(UPPER(ad.Addr1), '') + ' ' + isnull(UPPER(ad.Addr2), '') + ' ' + isnull(UPPER(ad.Addr3), '') + ' ' + isnull(UPPER(ad.Addr4), '')
,UPPER(ad.City)
,UPPER(ad.StateProvCd)
,ad.PostalCode
,i.EntityTypeCd
,isnull(tr.ReasonCd, '')
,cast(datediff(mm, th.transactioneffectivedt, bp.expirationdt) / cast(datediff(mm, bp.effectivedt, bp.expirationdt) AS DECIMAL(15, 4)) AS DECIMAL(15, 4))
,bd.YearBuilt
,ln.PROPDed + '%'
,CAST(bd.BldgNumber AS VARCHAR(255))
,CONVERT(INT,REPLACE(bd.BuildingValue,',',''))
,CONVERT(INT,REPLACE(bd.ContentsBLimit,',',''))
,CONVERT(INT,REPLACE(bd.ContentsCLimit,',',''))
,CONVERT(INT,REPLACE(bd.TIBLimit,',',''))
,CONVERT(INT,REPLACE(bd.BILimit,',',''))
,CONVERT(INT,REPLACE(bd.EDPLimit,',',''))
ORDER BY PolicyNumber, transactionnumber, bldgnumber
I get this result set:
What I want is to remove the duplicated transaction number 2 as you can see on the picture. I tried doing the max and group by function using the date and it didn't work. I tried it on transaction number, it works but introduced other problems. Is there anyway that I can get one result set? It is not a real duplicate, it has a different date but I only want to get the latest date that's why I figured the max function might work but I have to group by everything and that didn't help much. I have been looking at outer apply but I have never used that and I don't even know how I would use that on this particular problem.
Have you tried first_value?
FIRST_VALUE ( [scalar_expression ] )
OVER ( [ partition_by_clause ] order_by_clause [ rows_range_clause ] )
it works like this: you need to write DISTINCT
select **distinct** id,
first_value(transaction_effective_date) over (partition by number (,sup) order by date DESC (latest, ASC for oldest)) as last_trans_date
from table;
Documentation can be found here: https://msdn.microsoft.com/en-us/library/hh213018.aspx

SQL Server 2012, only show one row if other exists

Question:
I get these results (column task_externalId) when I run my query:
TC229090-10000-3
TC229090-20000-3
TC229830-10000-3
TC229685-10000-3
A task (TC229090) can contain multiple rows (10000, 20000), but can also have just one (10000 only).
My full code:
SELECT
v.voorgemeld_handmatig, v.voorgemeld, v.mac, v.orn, v.cdm, v.blo,
v.bco, v.tarcode, (v.timeslotfrom + ' - ' + v.timeslottill),
cast (case
when
(Select ac2.actionSpecificationName
From [COMTECdefault].[dbo].[task] t2
Join [COMTECdefault].[dbo].[actionKind] ak2 On t2.id_actionKind = ak2.id_actionKind
Join [COMTECdefault].[dbo].[actionSpecification] ac2 On ak2.id_actionSpecification = ac2.id_actionSpecification
where t2.task_externalId = (left(t.task_externalId, 15) + '2')) = 'laden'
then 'Vol'
else 'Leeg'
end as text) as IMPORT,
t.task_externalId, a.addressName, a.cityName,
CONVERT(DATE, t.from_date) as [Date],
CONVERT(varchar(8), CONVERT(TIME, t.from_date)) as [Tijd],
res.resourceName, resk.resourceKindName, r.shipOwner,
t.reference,
(Select resourceName
From [COMTECdefault].[dbo].[resource] r5
Left Outer Join [COMTECdefault].[dbo].resourceKind rk5 On rk5.id_resourceKind = r5.id_resourceKind
Where (id_resource = SUBSTRING(pt.StartResources, 0, CHARINDEX(',', pt.StartResources))
or id_resource = PARSENAME(REPLACE(SUBSTRING(pt.StartResources, CHARINDEX(',', pt.StartResources) + 1, LEN(pt.StartResources)), ',', '.'), 4)
or id_resource = PARSENAME(REPLACE(SUBSTRING(pt.StartResources, CHARINDEX(',', pt.StartResources) + 1, LEN(pt.StartResources)), ',', '.'), 3)
or id_resource = PARSENAME(REPLACE(SUBSTRING(pt.StartResources, CHARINDEX(',', pt.StartResources) + 1, LEN(pt.StartResources)), ',', '.'), 2)
or id_resource = PARSENAME(REPLACE(SUBSTRING(pt.StartResources, CHARINDEX(',', pt.StartResources) + 1, LEN(pt.StartResources)), ',', '.'), 1))
and r5.id_resourceKind = 51),
udo.udf_Gewicht, udo.udf_Zegelnummer,
cast (case when a.addressName = 'APM Terminal 2'
then case when udo.udf_Zegelnummer IS NULL
then 0
else 1
end
when a.addressName IN ('ect delta', 'Euromax Terminam C.V.', 'Euromax Terminal')
then case when udo.udf_Gewicht = 0
then 0
else 1
end
else 1
end as bit) as [voormelden],
v.foutcode, v.foutcode_tekst, v.V_door
FROM
[COMTECdefault].[dbo].[task] t
JOIN
[COMTECdefault].[dbo].[actionKind] ak ON t.id_actionKind = ak.id_actionKind
JOIN
[COMTECdefault].[dbo].[actionSpecification] ac ON ak.id_actionSpecification = ac.id_actionSpecification
LEFT OUTER JOIN
[COMTECdefault].[dbo].[resourceOrder] ro ON t.id_order = ro.id_order
LEFT OUTER JOIN
[COMTECdefault].[dbo].[resource] res ON ro.id_resource = res.id_resource
LEFT OUTER JOIN
[COMTECdefault].[dbo].[resourceKind] resk ON res.id_resourceKind= resk.id_resourceKind
LEFT OUTER JOIN
[COMTECdefault].[dbo].[address] a ON t.id_address = a.id_address
LEFT OUTER JOIN
[COMTECdefault].[dbo].[resourceOrder] r ON t.id_order = r.id_order
LEFT OUTER JOIN
[COMTECdefault].[dbo].[order] o ON o.id_order = r.id_order
LEFT OUTER JOIN
[COMTECdefault].[dbo].[voormelden] v ON v.id_task_otd = t.task_externalId
LEFT OUTER JOIN
[COMTECdefault].[dbo].[ud_order] udo ON udo.id_order = t.id_order
LEFT OUTER JOIN
[COMTECdefault].[dbo].[plannedTask] pt on t.id_task = pt.id_task
WHERE
(pt.id_Task IS NULL OR pt.taskstate <> 'finished')
AND (v.canceled IS NULL OR v.canceled = 0)
AND left(res.resourceName, 4) <> 'XXXU'
AND t.canceled = 0
AND (t.from_date <= '2016-11-24 23:59:59')
AND (ac.actionSpecificationName = 'inleveren')
AND a.addressName IN ('APM Terminal 1','APM Terminal 2', 'ect delta', 'rwg', 'Euromax Terminam C.V.', 'Euromax Terminal')
ORDER BY
res.resourceName, a.addressName, t.task_externalId
I only want to show the 20000 task when its exists . Otherwise show the 10000.
Thanks in advance.
I am not going to touch all of that text there may well be was of narrowing down all of the joins etc, but here is the pattern for doing what you want with the task_exteralid column.
DECLARE #Table AS TABLE (task_externalid VARCHAR(100))
INSERT INTO #Table VALUES
('TC229090-10000-3')
,('TC229090-20000-3')
,('TC229830-10000-3')
,('TC229685-10000-3')
;WITH cte AS (
SELECT
*
,RowNumber = ROW_NUMBER() OVER (PARTITION BY
LEFT(task_externalid,CHARINDEX('-',task_externalid) - 1)
ORDER BY task_externalid DESC)
FROM
#Table
)
SELECT *
FROM
cte
WHERE
RowNumber = 1
Create a partitioned ROW_NUMBER on the LEFT most portion of the task_exteralid
Order that by task_exteralid DESC

Not writing a value in XML with SQL Server

I have the following query which is part of a bigger XML. The issue is that is not writing the 0 value of the ELSE and writes an empty element <SellingLocation> in the XML. I can't find why. This is the query code.
SELECT (
SELECT TOP 1
CASE WHEN COUNT(ac.SKU) > 0
THEN l.ZoneId + ' ' + SUBSTRING(CONVERT(varchar(10), l.Bays), 0, 4)
ELSE 0
END
FROM #ARTSCreditTrans ac
INNER JOIN LocationSKU l ON ac.SKU = l.SKU
WHERE ac.PickTake = 'P'
GROUP BY ZoneId, Bays
)
FOR XML PATH('SellingLocation'), TYPE
#Devart, how can I make the same modification in the case of a query which has more that one option and the filter with the having doesn't look like the solution? For example:
SELECT [text()] = ISNULL((
SELECT TOP 1
CASE WHEN COUNT(oh.OrderNumber) > 0
THEN oh.Latitude
ELSE CASE WHEN td.RegisterID = 80
THEN SUBSTRING(tt.ShipMidInit, 1, CHARINDEX('|', tt.ShipMidInit) - 1)
END
END
FROM OrderHeader oh INNER JOIN TranDetail td ON oh.OrderNumber = td.DocNumber JOIN TranTotal tt ON td.DocNumber = tt.DocNumber
WHERE td.PickTake = 'P'
GROUP BY oh.Latitude, td.RegisterID, tt.ShipMidInit
), '')
FOR XML PATH('Latitude'), TYPE
Try wrapping the 0 in quotes ('):
SELECT (
SELECT TOP 1
CASE WHEN COUNT(ac.SKU) > 0
THEN l.ZoneId + ' ' + SUBSTRING(CONVERT(varchar(10), l.Bays), 0, 4)
ELSE '0'
END
FROM #ARTSCreditTrans ac INNER JOIN LocationSKU l ON ac.SKU = l.SKU
WHERE ac.PickTake = 'P'
GROUP BY ZoneId, Bays
)
FOR XML PATH('SellingLocation')
, TYPE
SELECT [text()] = ISNULL((
SELECT TOP 1 CAST(l.ZoneId AS VARCHAR(100)) + ' ' + CAST(l.Bays AS VARCHAR(5))
FROM #ARTSCreditTrans ac
JOIN dbo.LocationSKU l ON ac.SKU = l.SKU
WHERE ac.PickTake = 'P'
GROUP BY ZoneId, Bays
HAVING COUNT(ac.SKU) > 0
), '0')
FOR XML PATH('SellingLocation'), TYPE

How can I improve the performance of this select into query

I would appreciate if someone advises on how to improve the performance of a stored procedure with the following query (the functions are very small and I don’t believe they are penalising the performance):
SELECT DISTINCT REPLACE(REPLACE(REPLACE(c.[description], ' Org',''), ' group',''),'Organization full name','Org')
AS OrgColumn1,
REPLACE(REPLACE(c.[description], ' Org',''), ' group','') + ' Organization' AS OrgColumn2,
CASE
WHEN dbo.fn_OrgGrantPageAccess(c.id,#contactId) = 1
AND (c.id <> 13 AND c.id <> 31)
THEN '<a href="OrgMainPage.aspx?id='+CAST((c.id) as varchar(15))+'">'+
replace(replace(c.[description], ' Org',''), ' group','') + ' Org</a>'
WHEN dbo.fn_OrgGrantPageAccess(c.id,#contactId) = 1
AND (c.id = 13 OR c.id = 31)
THEN '<a href="OrgMainPage.aspx?id='+CAST((c.id) as varchar(15))+'">'+
c.[description]+'</a>'
ELSE
replace(replace(c.[description], ' Org',''), ' group','') + ' Org'
END AS OrgColumn3,
c.id AS OrgColumn4,
dbo.fn_OrgGetColumn5(c.id) AS OrgColumn5,
dbo.fn_OrgGetColumn6(c.id) AS OrgColumn6,
dbo.fn_OrgGetColumn7(c.id) AS OrgColumn7,
dbo.fn_OrgGetColumn8(c.id) AS OrgColumn8,
dbo.fn_OrgGetColumn9(c.id) AS OrgColumn9,
dbo.fn_OrgGetColumn10(c.id) AS OrgColumn10
INTO #T
FROM table_c c
INNER JOIN table_s s
ON c.id =s.id
INNER JOIN table_t t
ON s.type_id = t.type_id
LEFT OUTER JOIN table_m m
ON c.id = m.OrgID
LEFT OUTER JOIN table_cal cal
ON m.meetingid = cal.calid
WHERE t.type_id = 3
AND active = 1
AND (c.org_1 = 1
OR c.org_1 = 3)
ORDER BY OrgColumn1
I suggest you to rewrite dbo.fn_OrgGetColumn function from scalar-valued to table-valued and then cross apply it to main result set.
If you can provide source code for dbo.fn_OrgGetColumn function I can help you with rewriting it to table-valued.
There you can find good explanation with examples: Boost Your T-SQL with the APPLY

Resources