concatenation code column not found in a table using sql - sql

I have a table with few columns and I am trying to concatenate the code column with rank. But it throws me an error by saying code not found, this is in the concatenation I am doing with rank and code. The code column is a calculated column as you can see from the query. Could anyone please point me where I am doing a mistake?
table mm
ID cal_dtm rank milestone_hier_onb tr
CNT 1/31/2020 1 RFR EEZ
table dd
ID frs lst frst lst_s cal
CNT 6/20/2018 6/28/2018 6/28/2018 1/31/2020
Query
WITH r
AS (
SELECT dd.ID,
dd.frs,
dd.lst,
dd.frst,
dd.lst_s,
dd.cal_dtm,
mm.tr,
mm.ipf_rank,
mm.milestone_hier_onb
FROM dos dd
LEFT JOIN plw mm ON dd.ID = mm.ID
AND dd.cal_dtm = mm.cal_dtm
)
SELECT *
FROM (
SELECT r.ID,
r.cal_dtm,
'lp' AS code,
r.lst_s AS planned,
r.lst AS actual,
r.tr,
r.ipf_rank AS rank,
r.milestone_hier_onb AS onb,
* * CONCAT (
r.ipf_rank,
code
) AS milestone_label * *
FROM r
WHERE r.lst IS NOT NULL
UNION
SELECT r.ID,
r.cal_dtm,
'fp' AS code,
r.frst AS planned,
r.frs AS actual,
r.tr,
r.ipf_rank AS rank,
r.milestone_hier_onb AS onb,
* * CONCAT (
r.ipf_rank,
code
) AS milestone_label * *
FROM r
WHERE r.frs IS NOT NULL
)
ORDER BY ID,
cal_dtm,
code
Expected output
ID Cal code pl Al tr milestone_label rank onb
CNT 1/31/2020 lp 6/28/2018 6/28/2018 lp 1 1
CNT 1/31/2020 fp 6/20/2018

You can't use CODE like that; it is a constant so - concatenate that constant, e.g.
... 'lp' as code,
r.ipf_rank || 'lp' as milestone_label
...
How to add space?
r.ipf_rank ||' '|| 'lp' as milestone_label
or
r.ipf_rank ||' lp' as milestone_label

Let try:
remove order by
add alias **concat( r.ipf_rank, code) => **concat( r.ipf_rank, r.code)

Related

Select only the records with same values

I am working on a SQL statement that will become a part of a view. What I need is to extract only the records that have the same unique key twice. The query looks like below right now.
select distinct
rscmaster_no_in, rsc_no_in, calendar_year, calendar_month,
Wstat_Abrv_Ch,
h.Wstat_no_in, Staffing_Calendar_Date, payhours,
l.OTStatus
from
vw_all_ts_hire h
left join
MCFRS_OTStatus_Lookup l on l.wstat_no_in = h.Wstat_no_in
where
rscmaster_no_in in (select rscmaster_no_in from vw_rsc_ECC_splty)
and Wstat_Abrv_Ch <> ''
and h.Wstat_no_in in (103, 107)
and l.OTStatus in ('ECCOTRemove', 'ECCOTSignup')
and Staffing_Calendar_Date = '2020-11-01' -- only for the testing purposes. Will be removed later.
order by
RscMaster_no_in
The result I get from the query above is:
I need to modify the SQL statement so that the end result is like below:
How can I modify the above statement to spit out the end result like that?
Use the analytic count(*) over () function.
with cte as (
select
count(*) over (partition by YourUniqueKey) as MyRowCount
{rest of your query}
)
select *
from cte
where MyRowCount = 2;
This should give you the results you want (performance is dependent on indexes/table design).
This takes your core logic and puts it into a sub select that only returns records that have a count > 1.
Then use those ID's to select all the data you need but only for those ID's that are in the sub select with count > 1
select distinct rscmaster_no_in,rsc_no_in, calendar_year, calendar_month,
Wstat_Abrv_Ch, h.Wstat_no_in, Staffing_Calendar_Date, payhours ,l.OTStatus
from vw_all_ts_hire h
left join MCFRS_OTStatus_Lookup l on l.wstat_no_in = h.Wstat_no_in
WHERE rscmaster_no_in IN (
SELECT rscmaster_no_in
from vw_all_ts_hire h
left join MCFRS_OTStatus_Lookup l on l.wstat_no_in = h.Wstat_no_in
where rscmaster_no_in in (select rscmaster_no_in from vw_rsc_ECC_splty)
and Wstat_Abrv_Ch <> ''
and h.Wstat_no_in in (103, 107)
and l.OTStatus in ('ECCOTRemove', 'ECCOTSignup')
and Staffing_Calendar_Date = '2020-11-01' -- only for the testing purposes. Will be removed later.
GROUP BY rscmaster_no_in
HAVING COUNT(*) > 1
)
order by RscMaster_no_in
You can use COUNT(*) OVER () window function such as
SELECT *
FROM
(
SELECT COUNT(*) OVER (PARTITION BY rscmaster_no_in) AS cnt,
t.*
FROM tab t
) t
WHERE cnt>1
AND OTStatus = 'ECCOTRemove'
This may help you :
select * from (
select distinct
rscmaster_no_in, rsc_no_in, calendar_year, calendar_month,
Wstat_Abrv_Ch,
h.Wstat_no_in, Staffing_Calendar_Date, payhours,
l.OTStatus,
SELECT COUNT(*) OVER (PARTITION BY rscmaster_no_in) AS uinqueCount
from
vw_all_ts_hire h
left join
MCFRS_OTStatus_Lookup l on l.wstat_no_in = h.Wstat_no_in
where
rscmaster_no_in in (select rscmaster_no_in from vw_rsc_ECC_splty)
and Wstat_Abrv_Ch <> ''
and h.Wstat_no_in in (103, 107)
and l.OTStatus in ('ECCOTRemove', 'ECCOTSignup')
and Staffing_Calendar_Date = '2020-11-01' -- only for the testing purposes. Will be removed later.
) innerReult
where uinqueCount=2 --Or uinqueCount>1 base on your business
order by
RscMaster_no_in

For Pivot Columns need to apply group by

I want to apply the group by function based on columns generated by the PIVOT function.
In the query below, I wanted to apply Sum(TC.MB_Usage) so I could use group by at the end. However I am unable to apply the group by function to columns that are generated by the PIVOT function (SITES).
Comments are mentioned in BOLD
With TC as(
select /*+ NO_MERGE(T1) NO_MERGE(T2)
PARALLEL(T1,4) PARALLEL(T2,4) */
T1.* from (
select /*+
DRIVING_SITE(A) NO_MERGE(A) NO_MERGE(fips) NO_MERGE(fw) PARALLEL(A,4)
PARALLEL(fips,4) PARALLEL(fw,4) */
distinct
resource_value,
resource_type,
L3_IMSI as IMSI
,L9_Calling_Number as MDN
,L9_ECID as Curr_ECID
,trunc(START_TIME) as Usage_Date
,trim(TO_CHAR (TO_NUMBER (SUBSTR (L9_ECID,1,LENGTH(L9_ECID) - 2 ),'XXXXXXXXX'),'000000')) as enodeb
,substr(trim(TO_CHAR (TO_NUMBER (SUBSTR (L9_ECID,1,LENGTH(L9_ECID) - 2 ),'XXXXXXXXX'),'000000')),1,2) as fips_cd
,STATE_CODE
,STATE_NAME
,Sum(L3_ROUNDED_UNIT/1024) as MB_Usage
from RT_ET A
INNER JOIN
FIPS_STATEfips
ON trim(to_char(fips.FIPS_CODE,'00')) = substr(trim(TO_CHAR (TO_NUMBER (SUBSTR (A.L9_ECID,1,LENGTH(A.L9_ECID) - 2 ),'XXXXXXXXX'),'000000')),1,2)
INNER JOIN
DVC_ADDRfw
ON trim(L3_IMSI) = trim(to_char(FW.IMSI))
Where A.L9_ECID not in (' ','0') AND A.L3_IMSI not in (' ','0')
AND trunc(A.start_time) > trunc(sysdate-8)
AND trunc(start_time) > trunc(FW.ODS_INSERT_DATE)
group by
resource_value
,resource_type
,L3_IMSI
,L9_Calling_Number
,L9_ECID
,trunc(START_TIME)
,trim(TO_CHAR (TO_NUMBER (SUBSTR (L9_ECID,1,LENGTH(L9_ECID) - 2 ),'XXXXXXXXX'),'000000'))
,substr(trim(TO_CHAR (TO_NUMBER (SUBSTR (L9_ECID,1,LENGTH(L9_ECID) - 2 ),'XXXXXXXXX'),'000000')),1,2)
,STATE_CODE
,STATE_NAME
) T1
where NOT EXISTS (
SELECT
1 FROM DVC_ENODEB T2
WHERE T1.IMSI = trim(to_char(T2.IMSI))
AND T1.MDN = T2.MDN
AND T1.ENODEB = T2.ENODEB
)
)
select
distinct
SITES.*,
TC.resource_value,
TC.resource_type,
TC.IMSI,
TC.MDN,
TC.Curr_ECID,
TC.Usage_Date,
TC.enodeb,
TC.fips_cd,
TC.STATE_CODE,
TC.STATE_NAME,
**TC.MB_Usage -- Need to apply Sum(TC.MB_Usage)**
from
(
with
endb as
(select
e.IMSI, e.MDN,e.site_id, E.ENODEB,
ROW_NUMBER ()OVER (PARTITION BY e.IMSI||e.MDN
ORDER BY e.IMSI||e.MDN ) row_id
from
FIXED_WIRELESS_DVC_ADDR_ENODEB e
)
select *
from (select IMSI,MDN,IMSI||MDN as IMSI_MDN,site_id,row_id
from endb
)
pivot (max(site_id) siteid for row_id in (1,2,3,4,5,6,7,8,9,10,11,12,13)) ) SITES
INNER JOIN TC
ON ((TC.IMSI = trim(to_char(SITES.IMSI))) AND TC.MDN = SITES.MDN)
**Unable to apply Group by
based on below PIVOT columns (SITES.*), if I use SUM for MD_USAGE
Group BY
TC.resource_value,
TC.resource_type,
TC.IMSI,
TC.MDN,
TC.Curr_ECID,
TC.Usage_Date,
TC.enodeb,
TC.fips_cd,
TC.STATE_CODE,
TC.STATE_NAME,
SITES.***
You will need to specify the individual columns in your GROUP BY.
It looks like your SITES alias will have the columns IMSI, MDN, IMSI_MDN, and then 1,2,3,4,5,6,7,8,9,10,11,12,13 from the PIVOT clause.
So try listing those individually, and for the numeric ones put them in quotes:
GROUP BY
...
SITES."1", SITES."2", etc.

Using Analytical Clauses with DISTINCT

The purpose is to query multiple tables using DISTINC (if not I get millions of rows as results), but at the same time using sample to gather a 10% sample from the results that should all be unique. I am getting the following error:
ORA-01446: cannot select ROWID from, or sample, a view with DISTINCT, GROUP BY, etc.
Here is the code I have written:
WITH V AS (SELECT DISTINCT AL1."NO", AL3."IR", AL1."ACCT", AL3."CUST_DA", AL1."NA",
AL3."1_LINE", AL3."2_LINE", AL3."3_LINE", AL1."DA",
AL1."CD", AL1."TITLE_NA", AL1."ENT_NA", AL3."ACCT",
AL3."ACCTLNK_ENRL_CNT"
FROM "DOC"."DOCUMENT" AL1, "DOC"."VNDR" AL2, "DOC"."CUST_ACCT" AL3
WHERE (AL1."ACCT"=AL2."VNDR"
AND AL2."ACCT"=AL3."ACCT")
AND ((AL1."IMG_DA" >= Trunc(sysdate-1)
AND AL1."PROC"='A'
AND AL3."ACCT"<>'03')))
SELECT * FROM V SAMPLE(10.0)
You can't sample a join view like this.
Simpler test case (MCVE):
with v as
( select d1.dummy from dual d1
join dual d2 on d2.dummy = d1.dummy
)
select * from v sample(10);
Fails with:
ORA-01445: cannot select ROWID from, or sample, a join view without a key-preserved table
The simplest fix would be to move the sample clause to the driving table:
with v as
( select d1.dummy from dual sample(10) d1
join dual d2 on d2.dummy = d1.dummy
)
select * from v;
I would therefore rewrite your view as:
with v as
( select distinct
d.no
, a.ir
, d.acct
, a.cust_da
, d.na
, a."1_LINE", a."2_LINE", a."3_LINE"
, d.da, d.cd, d.title_na, d.ent_na
, a.acct
, a.acctlnk_enrl_cnt
from doc.document sample(10) d
join doc.vndr v
on v.vndr = d.acct
join doc.cust_acct a
on a.acct = v.acct
and d.img_da >= trunc(sysdate - 1)
and d.proc = 'A'
and a.acct <> '03'
)
select * from v;

SQL: Add all values from different rows

I have two SQL queries I want to combine into one. The first one selects all the IDs of the rows I need to add in the second one:
SELECT t.mp_id FROM t_mp AS t
JOIN t_mp_og USING (mp_id)
WHERE og_id = 2928
AND t.description = 'Energy'
The second one should add together the values from the rows returned by the first query. Up until now I've only been able to add several selects with a + in between them. For a dynamic query that adds all the rows returned by query one, I'd like to do something equivalent to "foreach(value from query1){ sum += value }" and return that sum.
SELECT(
(SELECT current_value FROM t_value_time WHERE mp_id = 29280001 AND time_id =
(SELECT time_id FROM t_time WHERE time_stamp =
(SELECT max(time_stamp) FROM v_value AS v WHERE time_stamp is not null AND mp_id = 29280001)))
+
(SELECT current_value FROM t_value_time WHERE mp_id = 29280015 AND time_id =
(SELECT time_id FROM t_time WHERE time_stamp =
(SELECT max(time_stamp) FROM v_value AS v WHERE time_stamp is not null AND mp_id = 29280015)))
+
(SELECT current_value FROM t_value_time WHERE mp_id = 29280022 AND time_id =
(SELECT time_id FROM t_time WHERE time_stamp =
(SELECT max(time_stamp) FROM v_value AS v WHERE time_stamp is not null AND mp_id = 29280022)))
);
My two problems: I don't know how to add all rows in a set, only the manual "+" way. I also don't know how to put the ID from the row into the SELECT getting the value. I've tried AS, but it seems to only work for tables, not single values.
Thanks for you help,
MrB
here is the edited query
select t.mp_id,sum(current_value)
from t_value_time t, t_time tim, v_value v
where
where t.mp_id = v.mp_id
and v.time_stamp is not null
and tim.time_stamp = MAX(v.time_stamp)
and t.time_id=tim.time_id
and t.mp_id in ( 29280001,29280015,29280022)
group by t.mp_id
use SUM() for aggregation
Have you tried SELECT Name, SUM(X) FROM Table GROUP BY Name
SELECT SUM(CURRENT_VALUE )
FROM
T_VALUE_TIME INNER JOIN T_TIME ON T_VALUE_TIME.TIME_ID=T_TIME.TIME_ID
JOIN V_VALUE ON T_TIME.TIME_STAMP=V_VALUE.TIME_STAMP
WHERE T_VALUE_TIME.MP_ID IN (SELECT t.mp_id FROM t_mp AS t JOIN t_mp_og USING (mp_id)
WHERE og_id = 2928
AND t.description = 'Energy' )
AND T_TIME.TIME_ID=(SELECT MAX(TIME_STAMP) FROM V_VALUE WHERE TIME_STAMP IS NOT NULL)
GROUP BY V_VALUE.MP_ID

Can you create nested WITH clauses for Common Table Expressions?

WITH y AS (
WITH x AS (
SELECT * FROM MyTable
)
SELECT * FROM x
)
SELECT * FROM y
Does something like this work? I tried it earlier but I couldn't get it to work.
While not strictly nested, you can use common table expressions to reuse previous queries in subsequent ones.
To do this, the form of the statement you are looking for would be
WITH x AS
(
SELECT * FROM MyTable
),
y AS
(
SELECT * FROM x
)
SELECT * FROM y
You can do the following, which is referred to as a recursive query:
WITH y
AS
(
SELECT x, y, z
FROM MyTable
WHERE [base_condition]
UNION ALL
SELECT x, y, z
FROM MyTable M
INNER JOIN y ON M.[some_other_condition] = y.[some_other_condition]
)
SELECT *
FROM y
You may not need this functionality. I've done the following just to organize my queries better:
WITH y
AS
(
SELECT *
FROM MyTable
WHERE [base_condition]
),
x
AS
(
SELECT *
FROM y
WHERE [something_else]
)
SELECT *
FROM x
With does not work embedded, but it does work consecutive
;WITH A AS(
...
),
B AS(
...
)
SELECT *
FROM A
UNION ALL
SELECT *
FROM B
EDIT
Fixed the syntax...
Also, have a look at the following example
SQLFiddle DEMO
These answers are pretty good, but as far as getting the items to order properly, you'd be better off looking at this article
http://dataeducation.com/dr-output-or-how-i-learned-to-stop-worrying-and-love-the-merge
Here's an example of his query.
WITH paths AS (
SELECT
EmployeeID,
CONVERT(VARCHAR(900), CONCAT('.', EmployeeID, '.')) AS FullPath
FROM EmployeeHierarchyWide
WHERE ManagerID IS NULL
UNION ALL
SELECT
ehw.EmployeeID,
CONVERT(VARCHAR(900), CONCAT(p.FullPath, ehw.EmployeeID, '.')) AS FullPath
FROM paths AS p
JOIN EmployeeHierarchyWide AS ehw ON ehw.ManagerID = p.EmployeeID
)
SELECT * FROM paths order by FullPath
we can create nested cte.please see the below cte in example
;with cte_data as
(
Select * from [HumanResources].[Department]
),cte_data1 as
(
Select * from [HumanResources].[Department]
)
select * from cte_data,cte_data1
I was trying to measure the time between events with the exception of what one entry that has multiple processes between the start and end. I needed this in the context of other single line processes.
I used a select with an inner join as my select statement within the Nth cte. The second cte I needed to extract the start date on X and end date on Y and used 1 as an id value to left join to put them on a single line.
Works for me, hope this helps.
cte_extract
as
(
select ps.Process as ProcessEvent
, ps.ProcessStartDate
, ps.ProcessEndDate
-- select strt.*
from dbo.tbl_some_table ps
inner join (select max(ProcessStatusId) ProcessStatusId
from dbo.tbl_some_table
where Process = 'some_extract_tbl'
and convert(varchar(10), ProcessStartDate, 112) < '29991231'
) strt on strt.ProcessStatusId = ps.ProcessStatusID
),
cte_rls
as
(
select 'Sample' as ProcessEvent,
x.ProcessStartDate, y.ProcessEndDate from (
select 1 as Id, ps.Process as ProcessEvent
, ps.ProcessStartDate
, ps.ProcessEndDate
-- select strt.*
from dbo.tbl_some_table ps
inner join (select max(ProcessStatusId) ProcessStatusId
from dbo.tbl_some_table
where Process = 'XX Prcss'
and convert(varchar(10), ProcessStartDate, 112) < '29991231'
) strt on strt.ProcessStatusId = ps.ProcessStatusID
) x
left join (
select 1 as Id, ps.Process as ProcessEvent
, ps.ProcessStartDate
, ps.ProcessEndDate
-- select strt.*
from dbo.tbl_some_table ps
inner join (select max(ProcessStatusId) ProcessStatusId
from dbo.tbl_some_table
where Process = 'YY Prcss Cmpltd'
and convert(varchar(10), ProcessEndDate, 112) < '29991231'
) enddt on enddt.ProcessStatusId = ps.ProcessStatusID
) y on y.Id = x.Id
),
.... other ctes
Nested 'With' is not supported, but you can always use the second With as a subquery, for example:
WITH A AS (
--WITH B AS ( SELECT COUNT(1) AS _CT FROM C ) SELECT CASE _CT WHEN 1 THEN 1 ELSE 0 END FROM B --doesn't work
SELECT CASE WHEN count = 1 THEN 1 ELSE 0 END AS CT FROM (SELECT COUNT(1) AS count FROM dual)
union all
select 100 AS CT from dual
)
select CT FROM A