How to get the value as per type from one column and display it as multiple column in hive? - hive

The below query will populate only check no and ac no even if there is data in rest of the column. How to populate all column from the value?
query:
select distinct * from(
select
(CASE WHEN b.dtl_typ = 'CheckNumber' THEN b.col_val END) as `Check Number`,
a.acc_id as Account_Number,
(CASE WHEN b.dtl_typ = 'AddressLine1' THEN b.col_val END) as `Address Line 1`,
(CASE WHEN b.dtl_typ = 'AddressLine2' THEN b.col_val END) as `Address Line 2`,
(CASE WHEN b.dtl_typ = 'City' THEN b.col_val END) as City,
(CASE WHEN b.dtl_typ = 'State' THEN b.col_val END) as State,
(CASE WHEN b.dtl_typ = 'Zipcode' THEN b.col_val END) as ZipCode
from
(select *from(select acc_id as acc_id, row_number() over(partition by acc_id order by booking_ts desc) rw_nbr
from TABLE1 where P_CODE = 'CheckTrnsfr' ) d where rw_nbr = 1) a
LEFT OUTER JOIN
(select acc_id, dtl_val as col_val, dtl_typ
from TABLE2 where dtl_typ in('AddressLine1','AddressLine2','City','State','Zipcode','CheckNumber')) b on b.acc_id = a.acc_id)a where
`Check Number` is not null
output:
expected output:The above picture only populate check no and a/c no and rest of the column is null even if the data is present which should not be happen. All column should populate with the available data.It is possible if i use more then one left join with where clause one by one like: dtl_typ= 'AddressLine1' left join dtl_typ='AddressLine2 and so on, but that should be a performance issue. It will hit DB multiple times.
select acc_id, dtl_val as col_val, dtl_typ from TABLE2 where dtl_typ in('AddressLine1','AddressLine2','City','State','Zipcode')
output:

Related

SQL Select a specific value in the group

I have this following table
Dept---------- Sub_Dept---- Dept Type
Sales.............Advertising........A
Sales.............Marketing......... B
Sales.............Analytics.......... C
Operations.....IT..................... C
Operations.....Settlement........C
And the result should be if a department got a department type as A then change all record of that department to A, else keep it same
Dept---------- Sub_Dept---- Dept Type
Sales.............Advertising........A
Sales.............Marketing......... A
Sales.............Analytics.......... A
Operations.....IT..................... C
Operations.....Settlement........C
Anybody can give a suggestion on this? I thought of using the GROUP BY but have to output the Sub Department as well
Thanks a lot
I would do:
update t
set depttype = 'a'
where exists (select 1 from t t2 where t2.dept = t.dept and t2.dept = 'a') and
t.dept <> 'a';
If you just want a select, then do:
select t.*,
(case when sum(case when depttype = 'a' then 1 else 0 end) over (partition by dept) > 1
then 'a'
else depttype
end) as new_depttype
from t;
Use below query
select a11.dept, a12.Sub_Dept, (case when a12.min_dep_type='A' then 'A' else a11.dep_type) as dep_type
from tab a11
JOIN (select dept, min(dep_type) min_dep_type from tab group by dept) a12
on a11.dept = a12.dept
Try this:
update table
set depttype= case when dept in (select dept from table where depttype='a') then 'a' else depttype end
This should work:
select a.dept, a.sub_dept,
case when b.dept is not null then 'A' else dept_type end as dept_type
from aTable a
left join(
select distinct Dept from aTable where dept_type = 'A'
)
b on b.dept = a.dept
You could use analytic functions to check whether exists the specific value in the group.
Try below query:
SELECT t.Dept,
t.Sub_Dept,
NVL(MIN(CASE WHEN t.Dept_Type = 'A'
THEN Dept_Type END) OVER (PARTITION BY t.Dept), t.Dept_Type) AS Dept_Type
FROM table_1 t
Using the analytic function MIN(), you can search for the value of 'A' (if it does exist inside the group). MIN works for non-null values only, so if you don't have any 'A' in the group, the result will be NULL.
At this point, you can use NVL to choose whether to print the value found in the group or the actual dept_type of the row.

Comparing two tables that doesn't have unique key

I need to compare two tables data and check which attributed are mismatching, tables have same table definition, but the problem is i dint have a unique key to compare. I tried to use
CONCAT(CONCAT(CONCAT(table1.A, Table1.B))
=CONCAT(CONCAT(CONCAT(table2.A, Table2.B))
but still facing duplicate rows also tried NVL on few columns but didn't work
SELECT
UT.cat,
PD.cat
FROM
EM UT, EM_63 PD
WHERE
NVL(UT.cat, 1) = NVL(PD.cat, 1) AND
NVL(UT.AT_NUMBER, 1) = NVL(PD.AT_NUMBER, 1) AND
NVL(UT.OFFSET, 1) = NVL(PD.OFFSET, 1) AND
NVL(UT.PROD, 1) = NVL(PD.PROD, 1)
;
There are 34k records in one table 35k records in another table, but if I run the above query, the count of rows is 3 millions.
Columns in table:
COUNTRY
CATEGORY
TYPE
DESCRIPTION
Sample data :
Table 1 :
COUNTRY CATEGORY TYPE DESCRIPTION
US C T1 In
IN A T2 OUT
B C T2 IN
Y C T1 INOUT
Table 2:
COUNTRY CATEGORY TYPE DESCRIPTION
US C T2 In
IN B T2 Out
Q C T2 IN
Expected output:
column Matched unmatched
COUNTRY 2 1
CATEGORY 2 1
TYPE 2 1
DESCRIPTION 3 0
In the most general case (when you may have duplicate rows, and you want to see which rows exist in one table but not in the other, and ALSO which rows may exist in both tables, but the row exists 3 times in the first table but 5 times in the other):
This is a very common problem with a settled "best solution" which for some reason it seems most people are still not aware of, even though it was developed on AskTom many years ago and has been presented numerous times.
You do NOT need a join, you do not need a unique key of any kind, and you don't need to read either table more than once. The idea is to add two columns to show from which table each row comes, do a UNION ALL, then GROUP BY all the columns except the "source" columns and show the count for each table. Something like this:
select count(t_1) as count_table_1, count(t_2) as count_table_2, col1, col2, ...
from (
select 'x' as t_1, null as t_2, col1, col2, ...
from table_1
union all
select null as t_1, 'x' as t_2, col1, col2, ...
from table_2
)
group by col1, col2, ...
having count(t_1) != count(t_2)
;
Start with this query to check if these 4 columns form a key.
select occ_total,occ_ut,occ_pd
,count(*) as records
from (select count (*) as occ_total
,count (case tab when 'UT' then 1 end) as occ_ut
,count (case tab when 'PD' then 1 end) as occ_pd
from select 'UT' as tab,cat,AT_NUMBER,OFFSET,PROD from EM
union all select 'PD' ,cat,AT_NUMBER,OFFSET,PROD from EM_63 PD
) t
group by cat,AT_NUMBER,OFFSET,PROD
) t
group by occ_total,occ_ut,occ_pd
order by records desc
;
After you have chosen your "key",you can use the following query to see the attributes' values
select count (*) as occ_total
,count (case tab when 'UT' then 1 end) as occ_ut
,count (case tab when 'PD' then 1 end) as occ_pd
,count (distinct att1) as cnt_dst_att1
,count (distinct att2) as cnt_dst_att2
,count (distinct att3) as cnt_dst_att3
,...
,listagg (case tab when 'UT' then att1 end) within group (order by att1) as att1_vals_ut
,listagg (case tab when 'PD' then att1 end) within group (order by att1) as att1_vals_pd
,listagg (case tab when 'UT' then att2 end) within group (order by att2) as att2_vals_ut
,listagg (case tab when 'PD' then att2 end) within group (order by att2) as att2_vals_pd
,listagg (case tab when 'UT' then att3 end) within group (order by att3) as att3_vals_ut
,listagg (case tab when 'PD' then att3 end) within group (order by att3) as att3_vals_pd
,...
from select 'UT' as tab,cat,AT_NUMBER,OFFSET,PROD,att1,att2,att3,... from E M
union all select 'PD' ,cat,AT_NUMBER,OFFSET,PROD,att1,att2,att3,... from EM_63 PD
) t
group by cat,AT_NUMBER,OFFSET,PROD
;
The problem with CONCATis, that you could get invalid matches, if your data looks similar to this:
table1.A = '123'
table1.B = '456'
concatenates to: '123456'
table2.A = '12'
table2.B = '3456'
concatenates also to: '123456'
You have to compare the fields individually: table1.A = table2.A AND table1.B = table2.B

Joining two SQL queries with different variations of data

I have this query which returns some data:
select
id, name, username, email, password,
first_name, last_name, usertype,
block, sendemail, registerDate, lastvisitDate,
activation, params, uuid
from
jml2_users
where
uuid in ('51840915-e570-430d-9911-7247d076f6e7', '51912193-6694-4ca5-94c9-9f31d076f6e7',
'51927ada-6370-4433-8a06-30d2d076f6e7', '51c05ad7-d1d0-4eb6-bc6b-424bd076f6e7',
'd047adf1-a6af-891e-94a2d0b225dcd1b6', '2aba38f2-d7a7-0a7a-eff2be3440e3b763')
and the other query is this
SELECT
ct.TrainingID, ct.UserID, ct.TrainingType, ct.TrainingStatus,
ct.TrainingScore, ct.TrainingDate,
dbo.fn_StripCharacters(ctt.product_type,'^a-z0-9') as product_type,
ctt.product_type as oldName
FROM
clientTraining as ct
INNER JOIN
clientTraningTypes as ctt ON ct.TrainingType = ctt.TypeID
WHERE
1=1
AND UserID IN ('51840915-e570-430d-9911-7247d076f6e7', '51927ada-6370-4433-‌​8a06-30d2d076f6e7')
AND TrainingType IN (SELECT TypeID
FROM complaincetestlinks
WHERE parent_client_id = 1039
AND isactive = 1 AND isdeleted = 0)
Both queries return different results, with userid and uuid in both tables have same data, I mean we can do a join, but the problem is: I want the second query data which are rows should be converted to columns in the new query and the data should be copied to new query with a join to the second query based on userid and uuid
I am noob at SQL and first question comes to me how do I convert the first query row data to columns and populate it with data because the first query has 5 rows. So eventually I need 5*4 = 20 columns for the new query and the data to be passed and uploaded to the new query from the second query
Not sure what I need to do here, I am lost
Here is an example of how to pivot the supplied query on product_type. I've only done some of the columns. Hopefully you can follow the example to add more.
SELECT
TrainingID,
UserID,
TrainingType,
TrainingStatus,
MAX(CASE
WHEN product_type = 'MarketLinkedCDs' THEN TrainingDate ELSE NULL
END) TrainingDate_MarketLinkedCDs,
MAX(CASE
WHEN product_type = 'StructuredNotes' THEN TrainingDate ELSE NULL
END) TrainingDate_StructuredNotes,
MAX(CASE
WHEN product_type = 'BufferedRangeAccrualNotes' THEN TrainingDate ELSE NULL
END) TrainingDate_BufferedRangeAccrualNotes,
MAX(CASE
WHEN product_type = 'MarketLinkedCDs' THEN TrainingScore ELSE NULL
END) TrainingScore_MarketLinkedCDs,
MAX(CASE
WHEN product_type = 'StructuredNotes' THEN TrainingScore ELSE NULL
END) TrainingScore_StructuredNotes,
MAX(CASE
WHEN product_type = 'BufferedRangeAccrualNotes' THEN TrainingScore ELSE NULL
END) TrainingScore_BufferedRangeAccrualNotes
FROM
(
SELECT ct.TrainingID, ct.UserID, ct.TrainingType, ct.TrainingStatus,
ct.TrainingScore,
ct.TrainingDate, dbo.fn_StripCharacters(ctt.product_type,'^a-z0-9') as product_type,
ctt.product_type as oldName FROM clientTraining as ct INNER JOIN
clientTraningTypes as ctt ON ct.TrainingType = ctt.TypeID WHERE 1=1 and
UserID in ('51840915-e570-430d-9911-7247d076f6e7',
'51927ada-6370-4433-‌​8a06-30d2d076f6e7')
and TrainingType IN (select TypeID from complaincetestlinks where
parent_client_id = 1039 and isactive = 1 and isdeleted = 0)
) F
GROUP BY
TrainingID,
UserID,
TrainingType,
TrainingStatus,

How to save in a variable the value of the following query? SQL Server

I need to implement two variables for save the data result in a query.
I have he following query:
SELECT * FROM
(SELECT location AS Location, COUNT(*) AS Trucks FROM Truck GROUP BY location) loc
OUTER APPLY
(
SELECT
COUNT(*) AS TotalOfCampaings,
SUM(CASE WHEN cc.campaing_status = 'Complete' THEN 1 ELSE 0 END) AS CampaingsWithCompleteStatus,
SUM(CASE WHEN cc.campaing_status = 'InProcess' THEN 1 ELSE 0 END) AS CampaingsWithInProcessStatus
FROM CampaingControl cc INNER JOIN Truck t ON cc.vin = t.vin
WHERE t.location = loc.location
) stat
This query shows the next table:
|Location|Trucks|TotalOfCampaings|CampaingsWithCompleteStatus|CampaingsWithInProcessStatus
I need to add a column at the end, in the new column i need to get the percent of campaings with complete status, i tried to do something like this:
Percent = (CampaingsWithCompleteStatus / TotalOfCamapings) * 100
But i dont know how to save the values of the query to do that.
Something like this:
SELECT
loc.Location,
loc.Trunks,
stat.TotalOfCampaings,
stat.CampaingsWithCompleteStatus,
stat.CampaingsWithInProcessStatus,
(1.0 * stat.CampaingsWithCompleteStatus /stat.TotalOfCampaings) * 100 as [Percent]
FROM
(SELECT location AS Location, COUNT(*) AS Trucks FROM Truck GROUP BY location) loc
OUTER APPLY
(
SELECT
COUNT(*) AS TotalOfCampaings,
SUM(CASE WHEN cc.campaing_status = 'Complete' THEN 1 ELSE 0 END) AS CampaingsWithCompleteStatus,
SUM(CASE WHEN cc.campaing_status = 'InProcess' THEN 1 ELSE 0 END) AS CampaingsWithInProcessStatus
FROM CampaingControl cc INNER JOIN Truck t ON cc.vin = t.vin
WHERE t.location = loc.location
) stat

Subqueries in MSSQL producing NULL values

I am trying to determine my store only accounts revenue from the database, to do this I need to look through all account numbers with revenue against a 'store' description who do NOT appear in a list of accounts with an 'online' description which I have tried todo in the subquery below. The query runs however it just returns NULL values in my store_only_revenue column. Any guidance on what to do from here would be appreciated. Am I approaching the problem in a good way? Or is there a better solution:
SELECT
town,
financial_pd as month,
SUM(CASE WHEN [Descr] = 'online' THEN Net_Revenue ELSE 0 END) as online_revenue,
SUM(CASE WHEN [Descr] = 'store' THEN Net_Revenue ELSE 0 END) as store_revenue,
COUNT(DISTINCT CASE WHEN [Descr] = 'online' THEN Account_Number ELSE NULL END) as online_accounts,
COUNT(DISTINCT CASE WHEN [Descr] = 'store' THEN Account_Number ELSE NULL END) as store_accounts,
(SELECT
SUM(Net_Revenue)
FROM [mydb].[dbo].[mytable]
WHERE
Descr = 'store'
AND Account_Number
NOT IN(
SELECT DISTINCT Account_Number
FROM [mydb].[dbo].[mytable]
WHERE
Descr = 'online')
) as store_only_revenue
FROM [mydb].[dbo].[mytable] as orders
WHERE
Group_name = 'T'
AND NOT
Type_name_1 = 'Electronic'
AND
Account_type <> 1
AND
Total_Value > 0
AND
(Insert_Date BETWEEN '2016-05-30' AND '2016-07-03'
OR
Insert_Date BETWEEN '2015-05-25' AND '2015-06-28')
OR
(Insert_Date BETWEEN '2016-05-30' AND '2016-07-03'
AND
Insert_Date BETWEEN '2015-05-25' AND '2015-06-28')
GROUP BY
town,
financial_pd as period
This expression is suspect:
Account_Number NOT IN (SELECT DISTINCT t.Account_Number
FROM [mydb].[dbo].mytable t
WHERE t.Descr = 'online'
)
Assuming that the syntax problems are typos (missing table name, desc is a reserved word), then this will never return true if even one Account_Number is NULL. One way to fix this is:
Account_Number NOT IN (SELECT t.Account_Number
FROM [mydb].[dbo].mytable t
WHERE t.Desc = 'online' AND t.Account_Number IS NOT NULL
)
I would use NOT EXISTS:
not exists (select 1
from [mydb].[dbo].??? x
where x.Desc = 'online' AND ??.Account_Number = x.Account_Number
)
You need to use proper table aliases for this to work. Either of these solutions may fix your problem.