Inner join with 3 tables and 2 sum groups - session

I have 3 tables; COMPANY, TRAINING TICKET and TEST.
COMPANY table:
COMPANY CODE | COMPANY NAME
192 ABC ENTERPRISE
299 XYZ ENTERPRISE
TRAINING TICKET table:
TICKET ID | COMPANY CODE | START DATE
2900 192 2015-02-02
3939 192 2015-03-03
4399 299 2015-03-02
TEST SESSION table:
TEST CODE | TICKET ID | COMPANY CODE | CERTIFIED
1221 2900 192 YES
2821 3939 192 NULL
3922 4399 299 YES
I need something like this:
C. CODE | COMPANY NAME | 1ST START DATE | TRAINING TICKET TOTAL | CERTIFIED TOTAL
192 ABC ENTERPRISE 2015-02-02 2 1
299 XYZ ENTERPRISE 2015-03-02 1 1
Its possible?
My Sql instruction is:
Select *, count(TICKET.CCODE) AS TICKET_TOTAL, count(TEST.CODE) AS CERT_TOTAL
from TICKET
Inner Join COMPANY on TICKET.CCODE = COMPANY.CCODE
Inner Join TEST on COMPANY.CCODE = TEST.CCODE
Group by (TICKET.CCODE),(TEST.CCODE)
Order by TICKET_TOTAL DESC
but both counts are always equals (same result for TICKET_TOTAL and CERT_TOTAL) and the sums are wrong - the result is TICKET_TOTAL = 21 and CERT_TOTAL = 28, but I got 523 - for TOP 1 company.

I got the answer:
Select COMPANY.CODE, COMPANY.NAME,
MIN(TICKET.STARTDATE), count(TICKET.TICKETID) AS TICKET_TOTAL,
count(TEST.CERTIFIED) AS CERT_TOTAL
from COMPANY
INNER JOIN TICKET ON COMPANY.CODE = TICKET.CCODE
LEFT JOIN TEST ON TICKET.TICKETID = TEST.TICKET
Group by (TICKET.CCODE)
ORDER BY TICKET_TOTAL DESC
1- Reorder and star the instruction from COMPANY TABLE
2- MIN(TICKET.STARTDATE) to got the First Start Date (Use MAX to got the Last Start Date if necessary)
3- Change Inner Join to Left Join (because some companies have a ticket on ticket table but does not have a test on test table)
Hope this can help someone in the future!

Related

How to fetch common item from two tables - Oracle

Scenario - I have users who are assigned different restrictions over several items. These restrictions are specified in restriction groups. Sometimes it happens that a user is a part of more than one restriction group. Sometimes, by mistake a user is assigned those restriction groups that have a conflict restriction for a common item. For example, User 123 is a part of restriction group A1 and B1 that have a common item Green Ball wherein restriction group A1 has a restriction that User 123 can access only 3 Green Balls a day while restriction group B1 says that User 123 can access only 2 Green Balls a day, thus leading to a conflict. I have to build a query that will fetch the information in such scenarios where there is a conflict. Every user belongs to a particular region, so the results will be filtered using region ID. My query should output.
UserId, Common Item, Restriction Group Name, Restriction
Tables
user - Id, userregionid
userRestriction - userId, restrictionGroup
restrictions- Item, restrictionGroup, restriction, interval // For example, Green Balls, Group A1, 3 , 1 (means 1 day)
My Effort -
select user.id,
userRestriction.restrictionGroup,
restrictions.Item,
restriction.restriction,
restriction.interval
from user left outer join userRestriction on user.Id = userRestriction.userId
left outer join restrictions on userRestriction.restrictionGroup = restriction.restrictionGroup
where user.useregionid= '12345'
group by userRestriction.userid,
user.id,
userRestriction.restrictionGroup,
restrictions.Item,
restriction.restriction,
restriction.interval,user.userregionid
having count(userRestriction.restrictiongroup)>1
I am getting nothing by running this query. This is not correct as I have data that should get resulted.
In my database, I have UserRestriction Table
UserId | RestrictionGroup
EID-999| A1
EID-888 | B1
EID-999 | C1
In the Restriction table
Item | RestrictionGroup| restriction | interval
GreenBalls| A1 | 1 | 1
Pen | B1 |1 | 7
GreenBalls|C1 |1 |30
The query should output
EID-999 | GreenBalls | A1 | 1 | 1
EID-999 | GreenBalls | C1 | 1 |30
User Table :
Id | userregionid
EID-999 | 12345
EID- 888 | 12345
D-900 | 2322
F-999 | 6767
The query should fetch only those users belonging to the specified userregionid.
I think there are some issues with your query. You can try below query -
select U.id,
UR.restrictionGroup,
R.Item,
R.restriction,
R.interval
from users U
left outer join userRestriction UR on U.Id = UR.userId
left outer join restrictions R on UR.restrictionGroup = R.restrictionGroup
where U.userregionid = 12345
group by U.id,
UR.restrictionGroup,
R.Item,
R.restriction,
R.interval
having count(UR.RestrictionGroup) >= 1
DB Fiddle

Reorder factored matrix columns in Power BI

I have a matrix visual in Power BI. The columns are departments and the rows years. The values are counts of people in each department each year. The departments obviously don't have a natural ordering, BUT I would like to reorder them using the total column count for each department in descending order.
For example, if Department C has 100 people total over the years (rows), and all the other departments have fewer, I want Department C to come first.
I have seen other solutions that add an index column, but this doesn't work very well for me because the "count of people" variable is what I want to index by and that doesn't already exist in my data. Rather it's a calculation based on individual people which each have a department and year.
If anyone can point me to an easy way of changing the column ordering/sorting that would be splendid!
| DeptA | DeptB | DeptC
------|-------|-------|-------
1900 | 2 | 5 | 10
2000 | 6 | 7 | 2
2010 | 10 | 1 | 12
2020 | 0 | 3 | 30
------|-------|-------|-------
Total | 18 | 16 | 54
Order: #2 #3 #1
I don't think there is a built-in way to do this like there is for sorting the rows (there should be though, so go vote for a similar idea here), but here's a possible workaround.
I will assume your source table is called Employees and looks something like this:
Department Year Value
A 1900 2
B 1900 5
C 1900 10
A 2000 6
B 2000 7
C 2000 2
A 2010 10
B 2010 1
C 2010 12
A 2020 0
B 2020 3
C 2020 30
First, create a new calculated table like this:
Depts = SUMMARIZE(Employees, Employees[Department], "Total", SUM(Employees[Value]))
This should give you a short table as follows:
Department Total
A 18
B 16
C 54
From this, you can easily rank the totals with a calculated column on this Depts table:
Rank = RANKX('Depts', 'Depts'[Total])
Make sure your new Depts table is related to the original Employees table on the Department column.
Under the Data tab, use Modeling > Sort by Column to sort Depts[Department] by Depts[Rank].
Finally, replace the Employees[Department] with Depts[Department] on your matrix visual and you should get the following:

Oracle Query Prevent Displayed Duplicate Record

Let's say i have a table structure like this :
ID | Name | SCHOOLNAME | CODESCHOOL
1 DARK Kindergarten 123 1
2 DARK Kindergarten 111 1
3 Knight NY University 3
4 Knight LA Senior HS 2
5 JOHN HARVARD 3
so, how to diplay all of the data above into like this :
ID | Name | SCHOOLNAME | CODESCHOOL
1 DARK Kindergarten 123 1
3 Knight NY University 3
5 JOHN HARVARD 3
my purpose is want to display data with the max of codeschool, but when i tried with my query below :
SELECT NAME, SCHOOLNAME, MAX(CODESCHOOL) FROM TABLE GROUP BY NAME, SCHOOLNAME
but the result is just like this :
ID | Name | SCHOOLNAME | CODESCHOOL
1 DARK Kindergarten 123 1
2 DARK Kindergarten 111 1
3 Knight NY University 3
4 Knight LA Senior HS 2
5 JOHN HARVARD 3
maybe it caused by the GROUP BY SCHOOLNAME, when i tried to not select SCHOOLNAME, the data displayed just like what i expected, but i need the SCHOOLNAME field for search condition in my query
hope you guys can help me out of this problem
any help will be appreciated
thanks
Using some wacky joins you can get a functional get max rows per category query.
What you essentially need to do is to join the table to itself and make sure that the joined values only contain the top values for the CODESCHOOL column.
I've also added a :schoolname parameter because you wanted to search by schoolname
Example:
SELECT
A.*
FROM
TABLE1 A
LEFT OUTER JOIN TABLE1 B ON B.NAME = A.NAME
AND B.CODESCHOOL < A.CODESCHOOL
WHERE
B.CODESCHOOL IS NULL AND
(
(A.SCHOOLNAME = :SCHOOLNAME AND :SCHOOLNAME IS NOT NULL) OR
(:SCHOOLNAME IS NULL)
);
this should create this output, note that dark has 2 outputs because it has 2 rows with the same code school which is the max in the dark "category"/name.
ID|NAME |SCHOOLNAME |CODESCHOOL
--| -----|----------------|----------
4|Knight|LA Senior HS | 2
5|JOHN |HARVARD | 3
2|DARK |Kindergarten 111| 1
1|DARK |Kindergarten 123| 1
It's not the most effective query but it should be more than good enough as a starting point.
Sidenote: I've been blatantly stealing this logic for a while from https://www.xaprb.com/blog/2007/03/14/how-to-find-the-max-row-per-group-in-sql-without-subqueries/
I am using an analytical window function ROW_NUMBER().
This will group (or partition) by NAME then select the top 1 CODESCHOOL in DESC order.
Select NAME,
SCHOOLNAME,
CODESCHOOL
From (
Select NAME,
SCHOOLNAME,
CODESCHOOL,
ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY CODESCHOOL DESC) as rn
from myTable)
Where rn = 1;

sort_array order by a different column, Hive

I have two columns, one of products, and one of the dates they were bought. I am able to order the dates by applying the sort_array(dates) function, but I want to be able to sort_array(products) by the purchase date.
Is there a way to do that in Hive?
Tablename is
ClientID Product Date
100 Shampoo 2016-01-02
101 Book 2016-02-04
100 Conditioner 2015-12-31
101 Bookmark 2016-07-10
100 Cream 2016-02-12
101 Book2 2016-01-03
Then, getting one row per customer:
select
clientID,
COLLECT_LIST(Product) as Prod_List,
sort_array(COLLECT_LIST(date)) as Date_Order
from tablename
group by 1;
As:
ClientID Prod_List Date_Order
100 ["Shampoo","Conditioner","Cream"] ["2015-12-31","2016-01-02","2016-02-12"]
101 ["Book","Bookmark","Book2"] ["2016-01-03","2016-02-04","2016-07-10"]
But what I want is the order of the products to be tied to the correct chronological order of purchases.
It is possible to do it using only built-in functions, but it is not a pretty site :-)
select clientid
,split(regexp_replace(concat_ws(',',sort_array(collect_list(concat_ws(':',cast(date as string),product)))),'[^:]*:([^,]*(,|$))','$1'),',') as prod_list
,sort_array(collect_list(date)) as date_order
from tablename
group by clientid
;
+----------+-----------------------------------+------------------------------------------+
| clientid | prod_list | date_order |
+----------+-----------------------------------+------------------------------------------+
| 100 | ["Conditioner","Shampoo","Cream"] | ["2015-12-31","2016-01-02","2016-02-12"] |
| 101 | ["Book2","Book","Bookmark"] | ["2016-01-03","2016-02-04","2016-07-10"] |
+----------+-----------------------------------+------------------------------------------+

Getting ORA-00937 although selected column is included in the GROUP By clause

Below is my SQL. I don't know what else to do to not receive "not a single-group group function" error.
SELECT PP.PENSIONERID,SUM(ROUND(EXP(SUM(LN(INFIDX)))*AMOUNT,2))AMOUNT
FROM AG_PEN_PARTS PP
JOIN LAG_INF_INDICES INF ON INF.INFYEAR>=EXTRACT(YEAR FROM PP.BEGDATE)
GROUP BY PP.PENSIONERID,PP.AMOUNT
I can't include ROUND(EXP(SUM(LN(INFIDX)))*AMOUNT,2) in the GROUP BY clause as group functions are not allowed there. Any ideas?
EDIT: Here're my two tables:
LAG_INF_INDICES: INFYEAR | INFIDX
----------------
2010 1.079
2011 1.116
2012 1.011
2013 1.024
AG_PEN_PARTS: PENSIONERID | BEGDATE | AMOUNT
------------------------------
112 07/20/2013 120
113 01/10/2012 100
112 12/12/2010 90
114 03/05/2011 70
here's the result I would expect to get:
PENSIONERID | AMOUNT
----------------------
112 235.08
113 103.53
114 80.87
So for instance, for the pensionerid 112 there're two records. First I need to multiply 90 with the multiplication of the INFIDX values beginning from 2010 and then 120 with the multiplication of the INFIDX values beginning from 2013 and then get sum of these two values.
To get this working, move the second SUM to another SELECT with a second GROUP BY:
SELECT PENSIONERID, SUM(AMOUNT) as AMOUNT FROM (
SELECT PP.PENSIONERID, ROUND(EXP(SUM(LN(INFIDX)))*AMOUNT,2) AMOUNT
FROM AG_PEN_PARTS PP
JOIN LAG_INF_INDICES INF ON INF.INFYEAR>=EXTRACT(YEAR FROM PP.BEGDATE)
GROUP BY PP.PENSIONERID, AMOUNT
) GROUP BY PENSIONERID
SQL Fiddle

Resources