Return record in single row if seafarer have more than 1 visa - MS SQL - sql

I need help. Currently below scripts will return more than 1 row if seafarer have more than 1 visa.
However, I need it to return single row, despite how many visa does seafarer have.
USE eCrewDos
GO
select distinct case mintab.sex
when 'M' then 'Mr.'
select distinct case mintab.sex
when 'M' then 'Mr.'
when 'F' then 'Ms.'
else 'Mr.'
end as 'Title:'
, mintab.LastName as 'Last Name:'
, mintab.MiddleName as 'Middle Name:'
, mintab.FirstName as 'First Name:'
, mintab.Sex as 'Gender'
, convert(varchar(10), mintab.DateOfBirth, 120) as 'Date of birth'
, mintab.PlaceOfBirth as 'Place of Birth:'
, countries.CountryName as 'Nationality:'
, contacts.MobilePhone1 as 'Mobile Phone 1:'
, contacts.Email1 as 'Email Address:'
, pass.PassportNo as 'Passport:'
, convert(varchar(10), pass.ValidityDateTo, 120) as 'Passport Expires:'
, pass.IssuedPlace as 'Passport - Issue Place:'
, pass.CountryName as 'Passport - Issue Country:'
, visa.DocumentName as 'Visa Name'
, visa.ReferenceNo as 'Visa Reference No'
, visa.CountryName as 'Visa - Issue Country'
, visa.issuedt as 'Visa - Issue Date'
, visa.expirydt as 'Visa - Expiry Date'
, lastserv.RankName as 'Position'
, airport.AirportCode + ' ' + airport.Name as 'Closest Airport'
, owners.CompanyName as 'Company name'
, vessels.VesselName as 'Vessel Name'
, mintab.SeafarerID as 'Seafarer ID'
from
(select distinct seafarers.SeafarerID
, seafarers.LastName
, seafarers.MiddleName
, seafarers.FirstName
, seafarers.Sex
, seafarers.DateOfBirth
, seafarers.PlaceOfBirth
, seafarers.CountryID
, max(services.StartDate) as startdate
from crewing.seafarers seafarers
left join crewing.Services services
on seafarers.SeafarerID = services.SeafarerID
, crewing.GeneralCompanies genco
where services.SeafarerID = seafarers.SeafarerID
and services.IsDeleted = 0
and seafarers.SeafarerID = services.SeafarerID
and services.ServiceType in ('C', 'H', 'P')
and services.StartDate > '2017-01-01'
--and seafarers.GeneralCompanyID not in (6, 8, 10, 21)
and seafarers.LastName not like 'Test%'
and seafarers.StatusID = 3
and seafarers.SubStatusID in (4, 5)
---- MODIFY THE BELOW DATE TO THE FIRST OF LAST MONTH ---------
and seafarers.LastModifiedDate > '2020-08-01'
group by seafarers.SeafarerID
, seafarers.LastName
, seafarers.MiddleName
, seafarers.FirstName
, seafarers.Sex
, seafarers.DateOfBirth
, seafarers.PlaceOfBirth
, seafarers.CountryID) mintab
left join
(select serv.SeafarerID
, ranks.RankName
, serv.VesselID
, max(serv.StartDate) as startdate
from crewing.services serv
, crewing.Ranks ranks
where serv.IsDeleted = 0
and serv.ServiceType in ('C', 'H', 'P')
and serv.RankID = ranks.RankId
group by serv.SeafarerID
, ranks.RankName
, serv.VesselID) lastserv
on (lastserv.SeafarerID = mintab.SeafarerID and lastserv.startdate = mintab.startdate)
left join
(select docs.SeafarerDocumentID
, docs.SeafarerID
, coun.CountryName
, passport.IssuedPlace
, passport.PassportNo
, docs.ValidityDateTo
from crewing.SeafarerDocuments docs
, crewing.SeafarerPassportDocuments passport
, crewing.Countries coun
where docs.seafarerDocumentID = passport.SeafarerDocumentID
and docs.IsDeleted = 0
and docs.DocumentCountryID = coun.CountryId) pass
on mintab.SeafarerID = pass.SeafarerID
left join
(select d.DocumentName
, srd.referenceno
, c.countryname
, c.countrycode
, convert(varchar(10)
, sd.ValidityDateFrom,120) issuedt
, convert(varchar(10),sd.ValidityDateTo,120) expirydt
, sd.SeafarerID
from crewing.SeafarerDocuments sd
join crewing.documents d on sd.DocumentID = d.documentid
join crewing.seafarerfiles sf on sd.seafarerfileid = sf.seafarerfileid
join crewing.countries c on sd.documentcountryid = c.countryid
join[eCrewDOS].[Crewing].[SeafarerReferenceDocuments] srd on srd.seafarerdocumentid =
sd.seafarerDocumentID
where d.documenttypeid = 16 and sd.validitydateto > getdate()) visa
on mintab.SeafarerID = visa.SeafarerID
, crewing.SeafarerContacts contacts
, crewing.Countries countries
, crewing.Airport airport
, crewing.SeafarerDocuments seafdocs
, crewing.vessels vessels
left join
crewing.Companies owners
on vessels.OwnerId = owners.CompanyId
left join
crewing.Companies managers
on vessels.managerId = managers.CompanyId
where mintab.CountryID = countries.CountryId
and contacts.AirportId = airport.AirportId
and mintab.SeafarerID = seafdocs.SeafarerID
and seafdocs.ValidityDateTo > getdate()
and seafdocs.DocumentID = 692
and seafdocs.IsDeleted = 0
and lastserv.VesselID = vessels.VesselId
and mintab.SeafarerID = contacts.SeafarerId
order by mintab.FirstName
--order by mintab.LastName, mintab.FirstName
Something like
Seafarer A - visa 1 xxx, visa 2 xxx, visa 3 xxx
Seafarer B - visa A xxx, visa 2 xxx
Seafarer C Visa A xxx
Please help.
Thank you

String Aggregate can be used to aggreagate multiple values to a single column
Please refer answer : List Aggreggate in SQL Server
For
Field A | Field B
1 | A
1 | B
2 | A
query
select FieldA, string_agg(FieldB, '') as data
from yourtable
group by FieldA
will give result
1 | AB
2 | A
For versions less than 2017 use
select distinct
SUBSTRING (
stuff(( select distinct ',' + [FieldB] from tablename order by 1 FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
,1,0,'' )
,2,9999)
from
tablename

Related

Bigquery similar query different output

I have 2 standard SQL queries in Bigquery. They are:
Query1:
select sfcase.case_id
, sfuser.user_id
, sfcase_create_date
, sfcase_status
, sfcase_origin
, sfcategory_category1
, sfcategory_category2
, sfcase_priority
, sftime_elapsedmin
, sftime_targetmin
, sfcase_sla_closemin
, if(count(sfcomment.parentid)=0,"0"
,if(count(sfcomment.parentid)=1,"1"
,if(count(sfcomment.parentid)=2,"2"
,"3"))) as comment_response
from(
select id as case_id
, timestamp_add(createddate, interval 7 hour) as sfcase_create_date
, status as sfcase_status
, origin as sfcase_origin
, priority as sfcase_priority
, case when status = 'Closed' then timestamp_diff(timestamp_add(closeddate, interval 7 hour),timestamp_add(createddate, interval 7 hour),minute)
end as sfcase_sla_closemin
, case_category__c
from `some_of_my_dataset.cs_case`
) sfcase
left join(
select upper(x1st_category__c) as sfcategory_category1
, upper(x2nd_category__c) as sfcategory_category2
, id
from `some_of_my_dataset.cs_case_category`
) sfcategory
on sfcategory.id = sfcase.case_category__c
left join(
select parentid as parentid
from `some_of_my_dataset.cs_case_comment`
) sfcomment
on sfcase.case_id = sfcomment.parentid
left join(
select ELAPSEDTIMEINMINS as sftime_elapsedmin
, TARGETRESPONSEINMINS as sftime_targetmin
, caseid
from `some_of_my_dataset.cs_case_milestone`
)sftime
on sfcase.case_id = sftime.caseid
left join(
select id as user_id
, createddate
from `some_of_my_dataset.cs_user`
)sfuser
on date(sfuser.createddate) = date(sfcase.sfcase_create_date)
group by 1
, 2
, 3
, 4
, 5
, 6
, 7
, 8
, 9
, 10
, 11
Query2:
select sfcase.id as case_id
, sfuser.id as user_id
, timestamp_add(sfcase.createddate, interval 7 hour) as sf_create_date
, sfcase.status as sf_status
, sfcase.origin as sf_origin
, upper(sfcategory.x1st_category__c) as sf_category1
, sfcategory.x2nd_category__c as sf_category2
, sfcase.priority as sf_priority
, sftime.ELAPSEDTIMEINMINS as sf_elapsedresponsemin
, sftime.TARGETRESPONSEINMINS as sf_targetresponsemin
, case when sfcase.status = 'Closed' then timestamp_diff(timestamp_add(sfcase.closeddate, interval 7 hour),timestamp_add(sfcase.createddate, interval 7 hour),minute)
end as sla_closemin
, if(count(sfcomment.parentid)=0,"0"
,if(count(sfcomment.parentid)=1,"1"
,if(count(sfcomment.parentid)=2,"2"
,"3"))) as comment_response
from `some_of_my_dataset.cs_case` as sfcase
left join `some_of_my_dataset.cs_case_category` as sfcategory
on sfcategory.id = sfcase.case_category__c
left join `some_of_my_dataset.cs_case_comment` as sfcomment
on sfcase.id = sfcomment.parentid
left join `some_of_my_dataset.cs_case_milestone` as sftime
on sfcase.id = sftime.caseid
left join `some_of_my_dataset.cs_user` as sfuser
on date(sfuser.createddate) = date(sfcase.createddate)
group by 1
, 2
, 3
, 4
, 5
, 6
, 7
, 8
, 9
, 10
, 11
I tried to run them in the same time. Query1 perform faster with less rows of data, while Query2 perform longer with more rows of data. Both of Query1 and Query2 have 12 columns.
Why do they return different result?
Which query should i use?
update: rename my dataset

Remove rows where one row offsets the next using accounting rules

I have a view of materials data which contains what was purchased and reversals of some of the purchases. I need a query that removes records that have reversals of purchase transactions. NOTE: The view does not have a primary key.
In the example I need to remove the first two rows as the second row offsets the first row because it reverses the purchase, but I need to keep the third row. Any ideas?
Here is the SQL for the view:
SELECT LEFT(mi.Plnt, 3) AS SBUID ,
oth.EQUIP AS PROJECTID ,
ms.Req_No AS GI ,
ms.Req_Item AS GI_LINE ,
CONVERT(VARCHAR(11), [Doc_Date], 100) + ' 12:00 AM' AS DOC_DATE ,
mi.[SLoc] AS SLOC ,
[Material] AS MATERIAL ,
mi.[Description] AS MATERIAL_DESCRIPTION ,
[Qty] AS QUANTITY ,
mi.[UoM] AS UOM ,
CASE WHEN mi.Mvt IN ( '101', '103', '105', '123', '261' ) THEN
mi.Amount
ELSE mi.Amount * -1
END AS Cost ,
mi.Amount AS EXT_ORG_COST ,
mi.PO AS [PO] ,
mi.Batch ,
mi.Vendor AS VENDOR ,
mi.VendorName AS VENDOR_NAME ,
at.AC_Group AS AC_TYPE ,
[Mvt] AS MVT
FROM [dbo].[MatIssued] mi
INNER JOIN dbo.OrderTableHistory oth ON oth.SUB_ORDER = mi.SubOrder
INNER JOIN dbo.Aircraft_Information2 ai ON ai.Equip = oth.EQUIP
INNER JOIN dbo.RFC_AcftTypeList at ON at.ID = ai.AC_TypeID
LEFT OUTER JOIN dbo.MatStatus ms ON ms.MPN = mi.Material
AND ms.SubOrder = mi.SubOrder
WHERE mi.Plnt IN ( '9131', '9132' )
AND mi.Mvt IN ( '101', '102', '103', '104', '105', '106', '122', '123' ,
'261' ,'262' )
AND mi.Doc_Date >= DATEADD(YEAR, -1, GETDATE())
ORDER BY mi.PO ,
mi.Batch ,
PROJECTID ,
mi.Mvt;
Some assumptions, based on your screenshot:
Reversals have same DOC_DATE as purchases
Reversals have same Batch as purchases
If the above assumptions are correct, try something like this:
DELETE FROM t
FROM MyTable t
WHERE EXISTS (
SELECT 1
FROM MyTable t2
WHERE
-- Join to outer table
t2.SLOC = t.SLOC
AND t2.MATERIAL = t.MATERIAL
AND t2.QUANTITY = t.QUANTITY
AND t2.PO = t.PO
AND t2.Batch = t.Batch
AND t2.VENDOR = t.VENDOR
GROUP BY SLOC, MATERIAL, QUANTITY, PO, Batch, VENDOR
HAVING COUNT(*) = 2 -- There are 2 matching rows
AND -MIN(QUANTITY) = MAX(QUANTITY) -- Minimum quantity negates Maximum quantity
AND MIN(COST) + MAX(COST) = 0 -- Costs cancel each other out
AND MIN(CASE WHEN Cost > 0 THEN DOC_DATE END) <= MIN(CASE WHEN Cost < 0 THEN DOC_DATE END) -- Purchase DOC_DATE less than or equal to reversal DOC_DATE
AND MIN(MVT) = MAX(MVT) + 1 -- Correlate purchase and reversal movement
AND (t.DOC_DATE = MIN(DOC_DATE) OR t.DOC_DATE = MAX(DOC_DATE)) -- Join to outer table
)

Shorten SQL statement not using a common table expression

The SQL below is written to return 'open orders'. This was written in a way I could understand but now I would like to try and optimize this and reduce the amount of code.
The SQL below gives me the desired outcome I'm looking for however, I would like to shorten the query without using WITH AS. Any suggestions using UNION or some other nesting method?
WITH
product AS --filter by dept
(SELECT item
, dept
FROM item_master
WHERE dept in ('353')
),
open_orders AS --view of orders in Status A with ordered units > received units
(SELECT ol.order_no
, ol.item
, ol.location
, oh.po_type
, oh.order_type
, oh.not_before_date
, oh.not_after_date
, oh.otb_eow_date
, SUM(ol.qty_ordered) AS qty_ordered
, SUM(NVL(ol.qty_received,0)) AS qty_received
FROM ordhead oh
, ordloc ol
WHERE oh.order_no = ol.order_no
AND oh.status = 'A'
AND ol.qty_ordered > NVL(ol.qty_received,0)
-- AND ol.order_no in ('18701212') --optional filter for specific PO's
GROUP BY ol.order_no
, ol.item
, ol.location
, oh.po_type
, oh.order_type
, oh.not_before_date
, oh.not_after_date
, oh.otb_eow_date
),
allocations AS --view of all allocations
(SELECT ah.alloc_no
, ah.order_no
, ah.item
, ad.to_loc
, NVL(ad.qty_allocated,0) AS qty_allocated
, NVL(ad.qty_received,0) AS qty_received
FROM alloc_header ah
, alloc_detail ad
WHERE ah.alloc_no = ad.alloc_no
)
SELECT p.dept --main query on above views
, oo.order_no
, oo.po_type
, oo.order_type
, oo.not_before_date
, oo.not_after_date
, oo.otb_eow_date
, oo.item
, CASE WHEN oo.po_type = 0 THEN oo.location ELSE aa.to_loc END AS loc
, SUM(oo.qty_ordered) AS order_qty
, CASE WHEN SUM(NVL(aa.qty_allocated,0)) - SUM(NVL(aa.qty_received,0)) = 0
THEN SUM(oo.qty_ordered) - SUM(NVL(oo.qty_received,0))
ELSE SUM(NVL(aa.qty_allocated,0)) - SUM(NVL(aa.qty_received,0))
END AS open_qty
FROM open_orders oo
, allocations aa
, product p
WHERE oo.order_no = aa.order_no(+)
AND oo.item = aa.item(+)
AND oo.item = p.item
AND (oo.qty_ordered - oo.qty_received) >0
GROUP BY p.dept
, oo.order_no
, oo.po_type
, oo.order_type
, oo.not_before_date
, oo.not_after_date
, oo.otb_eow_date
, oo.item
, CASE WHEN oo.po_type = 0 THEN oo.location ELSE aa.to_loc END
;
CTE's (Common Table Expressions) are just a way of organizing a query by sticking bits of code (that define a "derived" table) at the top that can be reused in the main statement. As such, where product, open_orders, and allocations are mentioned in the FROM clause, you can just swap those words out with the code that defines them:
SELECT p.dept --main query on above views
,
oo.order_no,
oo.po_type,
oo.order_type,
oo.not_before_date,
oo.not_after_date,
oo.otb_eow_date,
oo.item,
CASE
WHEN oo.po_type = 0
THEN oo.location
ELSE aa.to_loc
END AS loc,
SUM(oo.qty_ordered) AS order_qty,
CASE
WHEN SUM(NVL(aa.qty_allocated, 0)) - SUM(NVL(aa.qty_received, 0)) = 0
THEN SUM(oo.qty_ordered) - SUM(NVL(oo.qty_received, 0))
ELSE SUM(NVL(aa.qty_allocated, 0)) - SUM(NVL(aa.qty_received, 0))
END AS open_qty
FROM (
SELECT ol.order_no,
ol.item,
ol.location,
oh.po_type,
oh.order_type,
oh.not_before_date,
oh.not_after_date,
oh.otb_eow_date,
SUM(ol.qty_ordered) AS qty_ordered,
SUM(NVL(ol.qty_received, 0)) AS qty_received
FROM ordhead oh,
ordloc ol
WHERE oh.order_no = ol.order_no
AND oh.STATUS = 'A'
AND ol.qty_ordered > NVL(ol.qty_received, 0)
-- AND ol.order_no in ('18701212') --optional filter for specific PO's
GROUP BY ol.order_no,
ol.item,
ol.location,
oh.po_type,
oh.order_type,
oh.not_before_date,
oh.not_after_date,
oh.otb_eow_date
) oo,
(
SELECT ah.alloc_no,
ah.order_no,
ah.item,
ad.to_loc,
NVL(ad.qty_allocated, 0) AS qty_allocated,
NVL(ad.qty_received, 0) AS qty_received
FROM alloc_header ah,
alloc_detail ad
WHERE ah.alloc_no = ad.alloc_no
) aa,
(
SELECT item,
dept
FROM item_master
WHERE dept IN ('353')
) p
WHERE oo.order_no = aa.order_no(+)
AND oo.item = aa.item(+)
AND oo.item = p.item
AND (oo.qty_ordered - oo.qty_received) > 0
GROUP BY p.dept,
oo.order_no,
oo.po_type,
oo.order_type,
oo.not_before_date,
oo.not_after_date,
oo.otb_eow_date,
oo.item,
CASE
WHEN oo.po_type = 0
THEN oo.location
ELSE aa.to_loc
END;
This is obviously not shortened (but by a few characters), but I get the sense that "shortening" isn't your requirement. You are trying to get this query to work in a product that doesn't support CTEs.

Oracle SQL- Flag records based on record's date vs history

This is my 1st post on the forum. Usually I was able to find what I needed - but to tell the truth - I am not really sure how to ask a correct question to the issue. Therefore, please accept my apologies if there already is an answer on the forum and I missed it.
I am running the following code in an Oracle database via Benthic Software:
SELECT
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
, SUM(T4."VALUE")
,"HISTORICAL_PURCHASE_FLAG"
FROM
"DATABASE"."SALES" T4
, "DATABASE"."CUSTOMER" T1
, "DATABASE"."PRODUCT" T2
, "DATABASE"."TIME" T3
WHERE
T4."CUSTOMERID" = T1."CUSTOMERID"
AND T4."PRODUCTID" = T2."PRODUCTID"
AND T4."DATEID" = T3."DATEID"
AND T3."FISCALYEAR" IN ('2016')
AND T1."COUNTRY" IN ('ENGLAND', 'France')
GROUP BY
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
;
This query provides me with information on transactions. As you can see above, I would like to add a column named "HISTORICAL_PURCHASE_FLAG".
I would like the query to take CUSTOMER and FISCALYEARMONTH. Then, I would like to check if there are any transactions registered for the CUSTOMER, up to 2 years in the past.
So lets say I get the following result:
LineNum REGION COUNTRY IDNum CUSTOMER BUSSINESS FISCALYEARMONTH FISCALYEAR VALUE HISTORICAL_PURCHASE_FLAG
1 Europe ENGLAND 255 Abraxo Cleaner Co. Chemicals 201605 2016 34,567.00
2 Europe FRANCE 123 Metal Trade Heavy 201602 2016 12,500.00
3 Europe ENGLAND 255 Abraxo Cleaner Co. Chemicals 201601 2016 8,400.00
LineNum 1 shows transaction for Abraxo Cleaner Co. registered on 201605. And LineNum 3 is also for Abraxo Cleaner Co. but registered on 201601. What I would need the query to do, is to flag LineNum 1 as 'Existing'. Because there was a previous transaction registered.
On the other hand, LineNum 3 was the first time transactions was registered for Abraxo Cleaner Co. so the line would be flagged as 'New'.
To sum up, I would like for each row of data to be treated individually. And to check if there are any previous records of data for CUSTOMER & FISCALYEARMONTH - 24 months.
Thank you in advance for the help.
You can use LAG function:
SELECT
"REGION"
, "COUNTRY"
, "IDNum"
, "CUSTOMER"
, "BUSSINESS"
, "FISCALYEARMONTH"
, "FISCALYEAR"
, SUM("VALUE")
, MAX(CASE WHEN to_date(prev_fym,'YYYYMM') >= ADD_MONTHS (to_date("FISCALYEARMONTH",'YYYYMM'), -24) THEN 'Existing'
ELSE NULL END) "HISTORICAL_PURCHASE_FLAG"
FROM
(
SELECT
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
, T4."VALUE"
, LAG ("FISCALYEARMONTH", 1) OVER (PARTITION BY T1."IDNum" ORDER BY T3."FISCALYEARMONTH" DESC) prev_fym
FROM
"DATABASE"."SALES" T4
, "DATABASE"."CUSTOMER" T1
, "DATABASE"."PRODUCT" T2
, "DATABASE"."TIME" T3
WHERE
T4."CUSTOMERID" = T1."CUSTOMERID"
AND T4."PRODUCTID" = T2."PRODUCTID"
AND T4."DATEID" = T3."DATEID"
AND T1."COUNTRY" IN ('ENGLAND', 'France')
AND T3."FISCALYEAR" IN ('2014','2015','2016')
)
WHERE "FISCALYEAR" IN ('2016')
GROUP BY
"REGION"
, "COUNTRY"
, "IDNum"
, "CUSTOMER"
, "BUSSINESS"
, "FISCALYEARMONTH"
, "FISCALYEAR"
;
Using a simplified "input" table... You can use the LAG() analytic function and a comparison condition to populate your last column. I assume your fiscalyearmonth is a number - if it is a character field, wrap fiscalyearmonth within TO_NUMBER(). (It would be much better if in fact you stored these as true Oracle dates, perhaps date 2016-06-01 instead of 201606, but I worked with what you have currently... and took advantage that in numeric format, "24 months ago" simply means "subtract 200").
with inputs (linenum, idnum, fiscalyearmonth) as (
select 1, 255, 201605 from dual union all
select 2, 123, 201602 from dual union all
select 3, 255, 201601 from dual union all
select 4, 255, 201210 from dual
)
select linenum, idnum, fiscalyearmonth,
case when fiscalyearmonth
- lag(fiscalyearmonth)
over (partition by idnum order by fiscalyearmonth) < 200
then 'Existing' else 'New' end as flag
from inputs
order by linenum;
LINENUM IDNUM FISCALYEARMONTH FLAG
---------- ---------- --------------- --------
1 255 201605 Existing
2 123 201602 New
3 255 201601 New
4 255 201210 New
Another solution might be to outer Join "DATABASE"."SALES" T4 a second time as T5, wilter the fiscal year via WHERE to < t4.FiscalYear-2. If the Column is NULL, the record is new, if the outer join results in a value, the record is historic.
You can achieve using row_number() function as below... modify as per your need...I assumed 2 years (means previous 24 months from sysdate ).
You can run the sub-queries separately to check how its working.
Select
"REGION"
,"COUNTRY"
,"IDNum"
,"CUSTOMER"
,"BUSSINESS"
,"FISCALYEARMONTH"
,"FISCALYEAR"
,"VALUE"
, ( case when ( TXNNO = 1 or TOTAL_TXN_LAST24MTH = 0 ) then 'New' else 'Existing' end ) as "HISTORICAL_PURCHASE_FLAG" -- if no txn in last 24 month or its first txn then 'new' else 'existing'
from
(
select
SubQry."REGION"
, SubQry."COUNTRY"
, SubQry."IDNum"
, SubQry."CUSTOMER"
, SubQry."BUSSINESS"
, SubQry."FISCALYEARMONTH"
, SUBQRY."FISCALYEAR"
, SUBQRY."VALUE"
, ROW_NUMBER() over (partition by SUBQRY."REGION",SUBQRY."COUNTRY",SUBQRY."IDNum",SUBQRY."CUSTOMER",SUBQRY."BUSSINESS" order by SUBQRY."FISCALYEARMONTH") as TXNNO,
, SUM(case when (TO_NUMBER(TO_CHAR(sysdate,'YYYYMM')) - SUBQRY."FISCALYEARMONTH") < 24 then 1 else 0 end) as TOTAL_TXN_LAST24MTH
From
(
SELECT
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
, SUM(T4."VALUE") as VALUE
FROM
"DATABASE"."SALES" T4
, "DATABASE"."CUSTOMER" T1
, "DATABASE"."PRODUCT" T2
, "DATABASE"."TIME" T3
WHERE
T4."CUSTOMERID" = T1."CUSTOMERID"
AND T4."PRODUCTID" = T2."PRODUCTID"
AND T4."DATEID" = T3."DATEID"
AND T3."FISCALYEAR" IN ('2016')
AND T1."COUNTRY" IN ('ENGLAND', 'France')
GROUP BY
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
) SUBQRY
);

How can I change these into columns?

I've tried using CTE, but haven't been able to figure it out. I want to change the multiple rows into one row with multiple columns going accross. Any way to go about this...
Current Result
ern CostPool
111 NULL
111 5
Desired Result
ern CostPool1 CostPool2
111 NULL 5
SELECT first_name, last_name, ern, pc, title, TitleDesc, OfficeTitle, SUM(earned) earned, fypaydate, q
, [RMTS, Support, or Partial Quarter], SUM(CAST([Staff Employment Status] AS INT)) sumEmpStatus, SUM(CAST(countisMHy AS INT)) sumcountisMHy, SUM(CAST(sumisMHy AS INT)) sumisMHy1
, SUM(CAST(sumEligible AS INT)) sumEligible1
, CostPool
FROM (
SELECT
e.first_name, e.last_name
, fss.ern
, fss.pc
, fss4.title
, u.OfficeTitle
, t.TitleDesc
, SUM(fss.gross*fss.[percent]) earned
, fss.fypaydate, fss.q
, cpayfss3, cpaypdq
, CASE WHEN cpayfss3 = cpaypdq THEN '1' --full q
WHEN cpayfss3 < cpaypdq THEN '2' --part q
ELSE 'Check'
END [RMTS, Support, or Partial Quarter]
, CASE WHEN COUNT(DISTINCT rc.isMHy) = 2 THEN '9' --split
WHEN fss.pc = 'A' AND COUNT(DISTINCT rc.isMHy) = 1 AND SUM(CAST(rc.isMHy AS INT)) > 0 THEN '1' --full
WHEN fss.pc IN ('X', 'O', 'W', 'L', 'K') AND SUM(CAST(rc.isMHy AS INT)) > 0 THEN '2' --part
ELSE '0'
END [Staff Employment Status]
, COUNT(DISTINCT rc.isMHy) countisMHy
, SUM(CAST(rc.isMHy AS INT)) sumisMHy
, SUM(CAST(rc.Eligible AS INT)) sumEligible --count distinct too?
, rc.CostPool
FROM [FIN_DataMart].[dbo].[FSSpaydetl_NEW] fss
LEFT JOIN FIN_DataMart.[dbo].[FSSRC_NEW] rc
ON fss.newrc = rc.RC
AND fss.fypaydate = rc.FY
INNER JOIN
(
SELECT ern, fypaydate, q, COUNT(DISTINCT paydate) cpayfss3
FROM [FIN_DataMart].[dbo].[FSSpaydetl_NEW]
GROUP BY fypaydate, q, ern
) fss3
ON fss.ern = fss3.ern
AND fss.fypaydate = fss3.fypaydate
AND fss.q = fss3.q
LEFT JOIN
(
SELECT COUNT(DISTINCT paydate) cpaypdq, fy, q
FROM [FIN_DataMart].[dbo].[FSSPayDateQ]
GROUP BY fy, q
) pdq
ON fss.fypaydate = pdq.fy
AND fss.q = pdq.q
LEFT JOIN
[FIN_DataMart].[dbo].FSSEmployeeInfo e
ON fss.ern = e.ern
INNER JOIN
(
SELECT DISTINCT ern, title, tlvl, fy, q, ROW_NUMBER() OVER (PARTITION BY ern, fy, q ORDER BY title DESC) rn
FROM [FIN_DataMart].[dbo].[FSSpaydetl_NEW]
) fss4
ON fss.ern = fss4.ern
AND fss.fypaydate = fss4.fy
AND fss.q = fss4.q
AND fss4.rn = '1'
LEFT JOIN
(
SELECT TCode, TLevel, GenericTDesc as TitleDesc, EED,
ROW_NUMBER() OVER (PARTITION BY TCode, TLevel ORDER BY EED DESC) rn
FROM [FIN_DataMart].[dbo].FSATitle
) t
ON fss4.title = t.TCode
AND case when fss4.tlvl = '' THEN '01' WHEN fss4.tlvl IS NULL THEN '01' ELSE fss4.tlvl END = t.TLevel
AND t.rn = 1
LEFT JOIN FIN_DataMart.[dbo].[FSSUserERN] u
ON fss.ern = u.ern
WHERE fss.fypaydate = 2015
AND fss.q = 1
AND fss.obj <> '049' AND fss.obj NOT LIKE 'x%'
AND fss.title NOT IN ('10209', '1020B', '10234', '10232', '20202', '21205', '30086', '34201')
GROUP BY
fss.ern
, fss.pc
, fss4.title
, fss.fypaydate, fss.q
, cpayfss3, cpaypdq
, rc.CostPool
, t.TitleDesc
, e.first_name
, e.last_name
, u.OfficeTitle
HAVING SUM(CAST(rc.Eligible AS INT)) >=1
) A
GROUP BY
first_name, last_name, ern, pc, title, fypaydate, q
, [RMTS, Support, or Partial Quarter]
, OfficeTitle
, TitleDesc
, CostPool
ORDER BY first_name, last_name, fypaydate, q
You can look into using the Pivot operator to convert your rows into columns.
https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
That method would work, although your sample data and expected result do not quite match the massive query you have posted so I cannot provide a more specific example until you provide more test data/expected outputs (and table schema).