SQLPlus Spool CSV adding new line in columns - oracle-sqldeveloper

I need your help in spooling SQL output to formatted CSV below is the query producing the results -
set linesize 800
set pagesize 0 embedded ON
set underline off
col USERNAME format A12
COL USER_ID HEADING 'ID'
col USER_ID format 999
COL PASSWORD HEADING 'PWD'
col PASSWORD format a03
col ACCOUNT_STATUS format a18
col DEFAULT_TABLESPACE format a9
col DEFAULT_TABLESPACE heading 'DEF_TBS'
col TEMPORARY_TABLESPACE format a7
col TEMPORARY_TABLESPACE heading 'TMP_TBS'
col profile format a8
col INITIAL_RSRC_CONSUMER_GROUP format a22
col INITIAL_RSRC_CONSUMER_GROUP heading 'INIT_RSRC_CONSUMER_GRP'
col EXTERNAL_NAME heading 'EXT_NAME'
col EXTERNAL_NAME format a2
col EXPIRY_DATE heading 'EXP_DATE'
col PASSWORD_VERSIONS heading 'PWD_VERS'
set flush off
set echo off
set term off
set colsep ';'
set trimspool on
SELECT
u.username, u.user_id, u.account_status, u.created, u.lock_date, u.profile,
MAX(DECODE (up.resource_name, 'FAILED_LOGIN_ATTEMPTS', up.limit, '')) FAILED_LOGIN_ATTEMPTS,
MAX(DECODE (up.resource_name, 'PASSWORD_REUSE_TIME', up.limit, '')) PASSWORD_REUSE_TIME,
MAX(DECODE (up.resource_name, 'PASSWORD_VERIFY_FUNCTION', up.limit, '')) PASSWORD_VERIFY_FUNCTION,
MAX(DECODE (up.resource_name, 'PASSWORD_LOCK_TIME', up.limit, '')) PASSWORD_LOCK_TIME,
MAX(DECODE (up.resource_name, 'PASSWORD_REUSE_MAX', up.limit, '')) PASSWORD_REUSE_MAX,
MAX(DECODE (up.resource_name, 'PASSWORD_GRACE_TIME', up.limit, '')) PASSWORD_GRACE_TIME,
MAX(DECODE (up.resource_name, 'PASSWORD_LIFE_TIME', up.limit, '')) PASSWORD_LIFE_TIME
FROM dba_users u
INNER JOIN (SELECT p.profile, p.resource_name, DECODE(p.limit, 'DEFAULT', pd.limit, p.limit) limit
FROM dba_profiles p
LEFT JOIN dba_profiles pd ON p.resource_name = pd.resource_name AND p.resource_type = pd.resource_type AND pd.profile = 'DEFAULT'
WHERE p.resource_type = 'PASSWORD') up ON u.profile = up.profile
GROUP BY u.username, u.user_id, u.account_status, u.created, u.lock_date, u.profile;
The above code is resulting below csv - here columns are breaking in newline instead single rwo header, which is not expected.
USERNAME ; ID;ACCOUNT_STATUS ;CREATED ;LOCK_DATE;PROFILE ;FAILED_LOGIN_ATTEMPTS ;PASSWORD_REUSE_TIME ;PASSWORD_VERIFY_FUNCTION
PASSWORD_LOCK_TIME ;PASSWORD_REUSE_MAX ;PASSWORD_GRACE_TIME
PASSWORD_LIFE_TIME
The expected result is -

CSV Spooling is restored with correct alignment after the below parameters appended
col USERNAME for a25
col FAILED_LOGIN_ATTEMPTS for a25
col PASSWORD_VERIFY_FUNCTION for a25
col PASSWORD_REUSE_MAX for a25
col PASSWORD_LIFE_TIME for a25
col PASSWORD_LOCK_TIME for a25
col PASSWORD_GRACE_TIME for a25
col PROFILE for a18
col PASSWORD_REUSE_TIME for a25

Related

How to repeat some data points in query results?

I am trying to get the max date by account from 3 different tables and view those dates side by side. I created a separate query for each table, merged the results with UNION ALL, and then wrapped all that in a PIVOT.
The first 2 sections in the link/pic below show what I have been able to accomplish and the 3rd section is what I would like to do.
Query results by step
How can I get the results from 2 of the tables to repeat? Is that possible?
--define var_ent_type = 'ACOM'
--define var_ent_id = '52766'
--define var_dict_id = 113
SELECT
*
FROM
(
SELECT
E.ENTITY_TYPE,
E.ENTITY_ID,
'PERF_SUMMARY' as "TableName",
PS.DICTIONARY_ID,
to_char(MAX(PS.END_EFFECTIVE_DATE), 'YYYY-MM-DD') as "MaxDate"
FROM
RULESDBO.ENTITY E
INNER JOIN PERFORMDBO.PERF_SUMMARY PS ON (PS.ENTITY_ID = E.ENTITY_ID)
WHERE
1=1
-- AND E.ENTITY_TYPE = '&var_ent_type'
-- AND E.ENTITY_ID = '&var_ent_id'
AND PS.DICTIONARY_ID >= 100
AND (E.ACTIVE_STATUS <> 'N' )--and E.TERMINATION_DATE is null )
GROUP BY
E.ENTITY_TYPE,
E.ENTITY_ID,
'PERF_SUMMARY',
PS.DICTIONARY_ID
union all
SELECT
E.ENTITY_TYPE,
E.ENTITY_ID,
'POSITION' as "TableName",
0 as DICTIONARY_ID,
to_char(MAX(H.EFFECTIVE_DATE), 'YYYY-MM-DD') as "MaxDate"
FROM
RULESDBO.ENTITY E
INNER JOIN HOLDINGDBO.POSITION H ON (H.ENTITY_ID = E.ENTITY_ID)
WHERE
1=1
-- AND E.ENTITY_TYPE = '&var_ent_type'
-- AND E.ENTITY_ID = '&var_ent_id'
AND (E.ACTIVE_STATUS <> 'N' )--and E.TERMINATION_DATE is null )
GROUP BY
E.ENTITY_TYPE,
E.ENTITY_ID,
'POSITION',
1
union all
SELECT
E.ENTITY_TYPE,
E.ENTITY_ID,
'CASH_ACTIVITY' as "TableName",
0 as DICTIONARY_ID,
to_char(MAX(C.EFFECTIVE_DATE), 'YYYY-MM-DD') as "MaxDate"
FROM
RULESDBO.ENTITY E
INNER JOIN CASHDBO.CASH_ACTIVITY C ON (C.ENTITY_ID = E.ENTITY_ID)
WHERE
1=1
-- AND E.ENTITY_TYPE = '&var_ent_type'
-- AND E.ENTITY_ID = '&var_ent_id'
AND (E.ACTIVE_STATUS <> 'N' )--and E.TERMINATION_DATE is null )
GROUP BY
E.ENTITY_TYPE,
E.ENTITY_ID,
'CASH_ACTIVITY',
1
--ORDER BY
-- 2,3, 4
)
PIVOT
(
MAX("MaxDate")
FOR "TableName"
IN ('CASH_ACTIVITY', 'PERF_SUMMARY','POSITION')
)
Everything is possible. You only need a window function to make the value repeat across rows w/o data.
--Assuming current query is QC
With QC as (
...
)
select code, account, grouping,
--cash,
first_value(cash) over (partition by code, account order by grouping asc rows unbounded preceding) as cash_repeat,
perf,
--pos,
first_value(pos) over (partition by code, account order by grouping asc rows unbounded preceding) as pos_repeat
from QC
;
See first_value() help here: https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/FIRST_VALUE.html#GUID-D454EC3F-370C-4C64-9B11-33FCB10D95EC

Retrieve data from the same column in two columns

I have a table in PostgreSQL, something like this:
ID NAME
450 China
525 Germany
658 Austria
I’d like to query every names where ID < 500 and at the same time where ID > 500 and retrieve the result in two columns using
array_to_string(array_agg(NAME), ', ').
I need the following result:
column1 (ID < 500) column2 (ID > 500)
China Germany, Austria
Try using conditional aggregation:
SELECT
STRING_AGG(CASE WHEN ID < 500 THEN NAME END, ', ') AS ID_lt_500,
STRING_AGG(CASE WHEN ID >= 500 THEN NAME END, ', ') AS ID_gt_500
FROM yourTable;
Demo
Edit:
If you are using a version of Postgres which does not support STRING_AGG, then do as you were already doing:
SELECT
ARRAY_TO_STRING(ARRAY_AGG(CASE WHEN ID < 500 THEN NAME END), ', ') AS ID_lt_500,
ARRAY_TO_STRING(ARRAY_AGG(CASE WHEN ID >= 500 THEN NAME END), ', ') AS ID_gt_500
FROM yourTable;
Demo
Something like:
select (select string_agg(name, ', ')
from the_table
where id <= 500) as column1,
(select string_agg(name, ', ')
from the_table
where id > 500) as column2;
Alternatively:
select string_agg(name, ', ') filter (where id <= 500) as column1,
string_agg(name, ', ') filter (where id > 500) as column2
from the_table;

How to display solid line in a group when there is no value?

I need to display a solid line under year 2015 in my row group.
In a properties I entered my expression =IIF(Fields!YearNum.Value=2015,"Solid",Nothing)
But because some months don't have values the line is disrupted.
What would be the way to solve this problem?
Here is the t-sql for that tablix
SELECT CAST(B.YearNum as varchar(10))+ ' Submitted' as Type,
1 as OrderNum,
ISNULL(COUNT( ControlNo),0) Count,
b.YearNum, b.MonthNum, b.MonthName
FROM tblCalendar b
LEFT JOIN ClearanceReportMetrics a ON b.MonthNum = MONTH(a.EffectiveDate) AND b.YearNum=YEAR(a.EffectiveDate)
AND CompanyLine = 'Argonaut Insurance Company' AND Underwriter <> 'Batcheller, Jerry'
WHERE YEAR(EffectiveDate) IN (2016, 2015)
GROUP BY b.YearNum, b.MonthNum,b.MonthName
UNION ALL
SELECT CAST(b.YearNum as varchar(10)) +' Quoted' as Type,
2 as OrderNum,
ISNULL(SUM(CASE WHEN QuotedPremium IS NOT NULL THEN 1 ELSE 0 END),0) as Count,
b.YearNum, b.MonthNum,b.MonthName
FROM tblCalendar b
LEFT JOIN ClearanceReportMetrics a ON b.MonthNum = MONTH(a.EffectiveDate) AND b.YearNum=YEAR(a.EffectiveDate)
AND CompanyLine = 'Argonaut Insurance Company' AND Underwriter <> 'Batcheller, Jerry'
WHERE YEAR(EffectiveDate) IN (2016, 2015) --AND CompanyLine = 'Plaza Insurance Company' AND Underwriter <> 'Batcheller, Jerry'
GROUP BY b.YearNum, b.MonthNum,b.MonthName
UNION ALL
SELECT CAST(b.YearNum as varchar(10)) +' Bound' as Type,
3 as OrderNum,
ISNULL(sum(case when TransactionType = 'Policy' then 1 ELSE 0 END),0) as Binds,
b.YearNum,
b.MonthNum,
b.MonthName
FROM tblCalendar b
LEFT JOIN ProductionReportMetrics a ON b.MonthNum = MONTH(a.EffectiveDate) and b.YearNum = YEAR(a.EffectiveDate) --Coming from Production Report, NOT from Clearance!!!!!!!!!!!
AND CompanyLine = 'Argonaut Insurance Company' AND Underwriter <> 'Batcheller, Jerry'
WHERE b.YearNum IN (2016, 2015)
GROUP BY b.YearNum,b.MonthNum,b.MonthName
UNION ALL
SELECT CAST(b.YearNum as varchar(10)) +' Declined' as Type,
4 as OrderNum,
ISNULL(SUM(CASE WHEN Status = 'Declined' THEN 1 ELSE 0 END ),0) as Count,
b.YearNum, b.MonthNum,b.MonthName
FROM tblCalendar b
LEFT JOIN ClearanceReportMetrics a ON b.MonthNum = MONTH(a.EffectiveDate) AND b.YearNum=YEAR(a.EffectiveDate)
AND CompanyLine = 'Argonaut Insurance Company' AND Underwriter <> 'Batcheller, Jerry'
WHERE YEAR(EffectiveDate) IN (2016, 2015)
GROUP BY b.YearNum, b.MonthNum,b.MonthName
Also tried to change NULL values to 0. But still gives me the same result
You can handle missing values like this:
=IIF(Fields!YearNum.Value=2015 Or IsNothing(Fields!YearNum.Value) = 1,"Solid",Nothing)
The workaround I found is:
In the properties, BotderStyle
For Top I wrote expression:
=IIF(Fields!Type.Value="2016 Quoted","Solid",
IIF(Fields!Type.Value="2016 Bound","Solid",
IIF(Fields!Type.Value="2016 Declined","Solid",
Nothing)))
And for the Bottom expression:
=IIF(Fields!Type.Value="2015 Submitted","Solid",
IIF(Fields!Type.Value="2015 Quoted","Solid",
IIF(Fields!Type.Value="2015 Bound","Solid",
Nothing)))
So basically those lines cancelling each other off, and filling up the gaps.

Pivot table with dynamic columns in date order

I have a pivot table creating 2 columns for each line that I would like to go in date order.
Below is the data in the raw format
-------------------------------------------------------------
partnum | period | TotalQty | ToldSold
005483-6 | 2015-08 | 100.00000000 | 389.379000
0551105 | 2015-08 | 10.00000000 | 4560.773000
0CT202305 | 2015-09 | 4.00000000 | 2285.430800
0CTR00905 | 2015-10 | 2.00000000 | 654.305400
183386-32 | 2016-01 | 20.00000000 | 75.060400
24-175UV50| 2016-03 | 450.00000000 | 42.723000
I have the following code to generate the dynamic pivot table
DECLARE #cols AS NVARCHAR(MAX),
#colsName AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(period +'_'+c.col)
from #orderhistory
cross apply
(
select 'TotalQty' col
union all
select 'ToldSold'
) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #cols
select #colsName
= STUFF((SELECT distinct ', ' + QUOTENAME(period +'_'+c.col)
+' as ['
+ period + case when c.col = 'TotalQty' then ' QtySold]' else 'Total $ Sold]' end
from #orderhistory
cross apply
(
select 'TotalQty' col
union all
select 'ToldSold'
) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsName
set #query
= 'SELECT partnum, ' + #colsName + '
from
(
select
partnum,
period +''_''+col col,
value
from
(
select partnum,
period,
cast(TotalQty as numeric(10, 2)) TotalQty,
cast(ToldSold as numeric(10, 2)) ToldSold
from #orderhistory
) src
unpivot
(
value
for col in (TotalQty, ToldSold)
) unpiv
) s
pivot
(
sum(value)
for col in (' + #cols + ')
) p
order by partnum'
execute(#query)
It creates data like the following
partnum 2016-02 QtySold 2015-08Total $ Sold 2015-11Total $ Sold 2015-12 QtySold
005483-10 NULL NULL NULL 100.00
005483-12 NULL NULL 1249.68 450.00
005483-14 NULL NULL NULL 70.00
005483-2 NULL NULL 1234.19 350.00
005483-3 10.00 NULL NULL NULL
What I would like to see is the headers go across in date order
partnum | 2015-08 QtySold | 2015-08 Total $ Sold | 2015-09 QtySold | 2015-09 Total $ Sold........
All the way across until I get to my current month.
I think I need to add an order by somewhere, I just don't know where. This is my first multiple column dynamic pivot table so I'm a little lost. Everywhere i have tried has given me some sort of error.
Any help is greatly appreciated!!
you would order your #colNames data..
SELECT #colsName = STUFF((
SELECT DISTINCT
', '
+ QUOTENAME(period + '_' + c.col)
+ ' as ['
+ period
+ CASE WHEN c.col = 'TotalQty' THEN ' QtySold]' ELSE 'Total $ Sold]' END
FROM #orderhistory
CROSS APPLY (SELECT 'TotalQty' col UNION ALL SELECT 'ToldSold') c
--ORDER BY HERE
ORDER BY period, c.col
FOR XML PATH(''), TYPE
).value('.','NVARCHAR(MAX)'),1,1,'')

Connecting two queries into one

I got such two queries:
SELECT
count (C.CaseDetailsId) as [Z telefonem]
,U.FirstName + ' ' + U.LastName as [Windykator]
from CaseDetails as C
join DebtorDetails as D on C.CaseDetailsId = D.CaseDetailsId
join Users as U on C.UserId = U.UserId
where D.DebtorDetailsId in
(SELECT DebtorDetailsId from DebtorPhone
where (IsValid = 'True') or (IsDefault = 'True'))
and C.CaseStatusId <> 2 and C.CaseStatusId <> 6 group by U.FirstName,U.LastName
e
and
SELECT
count (CaseDetailsId) as [Beztel]
,U.FirstName + ' ' + U.LastName as [Windykator]
from CaseDetails as C
join Users as U on C.UserId = U.UserId
where
C.CaseStatusId <> 2 and C.CaseStatusId <> 6 group by U.FirstName,U.LastName
I need to group the results of those two into 1 table so I suppose it would be best to connect them but I have no idea how to do it.
The query has to count rows in two cases
1) overall
2) where exists a specified row in another table
So in general -> I need to count number of cases (CaseDetailsId) for every employeer (Users) with and without phone number (DebtorPhones)
Below query will give you one record set from two queries using union. You can add insert statement above select to insert into your required table.
SELECT Count (C.casedetailsid) AS [Z telefonem],
U.firstname + ' ' + U.lastname AS [Windykator]
FROM casedetails AS C
JOIN debtordetails AS D
ON C.casedetailsid = D.casedetailsid
JOIN users AS U
ON C.userid = U.userid
WHERE D.debtordetailsid IN (SELECT debtordetailsid
FROM debtorphone
WHERE ( isvalid = 'True' )
OR ( isdefault = 'True' ))
AND C.casestatusid <> 2
AND C.casestatusid <> 6
GROUP BY U.firstname,
U.lastname
Union
SELECT Count (casedetailsid) AS [Z telefonem],
U.firstname + ' ' + U.lastname AS [Windykator]
FROM casedetails AS C
JOIN users AS U
ON C.userid = U.userid
WHERE C.casestatusid <> 2
AND C.casestatusid <> 6
GROUP BY U.firstname,
U.lastname
#Pratik Kaje not really. It shows 2 columns only - [Z tel] and [Windykator]
I tested a bit and ended with such query:
SELECT
[Windykator]
,[Beztel]
,[Z telefonem]
from
(SELECT
count (C.CaseDetailsId) as [Z telefonem]
,NULL as [Beztel]
,NULL as [Windykator]
from CaseDetails as C
join DebtorDetails as D on C.CaseDetailsId = D.CaseDetailsId
join Users as U on C.UserId = U.UserId
where D.DebtorDetailsId in
(SELECT DebtorDetailsId from DebtorPhone
where (IsValid = 'True') or (IsDefault = 'True'))
and C.CaseStatusId <> 2 and C.CaseStatusId <> 6
group by U.FirstName, U.LastName
UNION ALL
SELECT
NULL
,count (CaseDetailsId) as [Beztel]
,NULL
from CaseDetails as C
join Users as U on C.UserId = U.UserId
where
C.CaseStatusId <> 2 and C.CaseStatusId <> 6
group by U.FirstName, U.LastName
UNION ALL
SELECT
NULL
,NULL
,U.FirstName + ' ' + U.LastName
from CaseDetails as C
join Users as U on C.UserId = U.UserId
where
C.CaseStatusId <> 2 and C.CaseStatusId <> 6
group by U.FirstName, U.LastName
) as x
Almost perfectly however the results are not grouped. So it shows results with
NULLS NULLS [Bez tel]
NULLS [Z tel] NULLS
[Windykator] NULLS NULLS