t/sql query with two different tables - sql

i need to create an oracle select statement that returns acct,name,city,splitcost from table1 and APIcost from table2. table1 splits the 90 into 3 diff. amounts because they are distributed elsewhere. table2 is the API download that only has 1 record of the total 90. if i use inner join the 90 repeats on each row linking by acct. i need the results to look like the second view only show APIcost total 90. once per acct.
hope this makes sense. if i was using sql I'm prob. do a temp table but it has to be done in Oracle which i'm not used too.

No need for a temp table, just build a rank and do a case statement on it to populate the first row with the api_cost. I don't know which row you want, so play with the "order by" clause to get that to do the row you want.
/* Building out your data to a "temp table" */
with table1 as
(select 1111 as acct, 'john' as name, 'hampton' as city, 30 as split_cost, 90 as
api_cost from dual union all
select 1111 as acct, 'john' as name, 'hampton' as city, 40 as split_cost, 90 as
api_cost from dual union all
select 1111 as acct, 'john' as name, 'hampton' as city, 20 as split_cost, 90 as
api_cost from dual union all
select 1111 as acct, 'john' as name, 'hampton' as city, 20 as split_cost, 90 as
api_cost from dual)
/* You need nothing above here, just below */
select acct, name, city, split_cost,
case when rank() over (partition by acct, name, city order by split_cost, rownum) =
1 then api_cost
else null
end as api_cost
from table1; --substitute your table name here
OUTPUT:
ACCT NAME CITY SPLIT_COST API_COST
1111 john hampton 20 90
1111 john hampton 20
1111 john hampton 30
1111 john hampton 40

Related

SQL getting multiple rows in PARTICULAR sql

I have a table abc with following rows:
emp_id_role Group_name Role_name Location_id
12 Insurance Manager Noida
12 Insurance Senior Manager Noida
13 Global Client Services Sw UP
14 Operations Management All Jobs kERALA
and another master table with all the details employee_xyz:
PERSON_ID NAME DOB START_DATE END_DATE SSN
12 DEAN 01-JAN-1990 01-JAN-2017 20-JAN-2017 847474
12 DEAN 01-JAN-1990 21-JAN-2017 03-mar-2018 847474
12 DEAN 01-JAN-1990 04-mar2018 31-DEC-4712 847474
13 SAM 20-JAN-1990 17-JAN-2016 20-JAN-2017 847474
13 SAM 20-JAN-1990 21-JAN-2017 31-DEC-4712 847474
14 JAY 29-dec-1990 21-JAN-2016 31-DEC-4712 847474
I want to fetch the full names from the table employee_xyz for the records in table abc.
When I'm joining these two using the below queries I'm getting more number of rows for an employee than in table abc,
Eg: for employee_id 12 I should get 2 rows as in table abc but I'm getting 9 rows somehow...
Query used is simple :
select * from table_abc abc,
employee_xyz xyz
where xyz.person_id=abc.emp_id_role
and trunc(sysdate) between abc.Start_date and xyz.end_date
and person_id=12;
I suppose you want to select all columns from table_abc with names from employee_xyz.
If your try with select abc.*, xyz.name, you already able to select as two rows since sysdate for person_id= 12 stays in the interval only for third row(start_date:04-mar2018/ end_date:31-DEC-4712) but if you want non-repeating even with more date values stay, you can use distinct : select distinct abc.*, xyz.name as below( where there're two rows in the interval second row's end date converted from '2018-03-03' to '2019-03-03' ) :
with table_abc(emp_id_role, Group_name, Role_name, Location_id) as
(
select 12,'Insurance','Manager','Noida' from dual union all
select 12,'Insurance','Senior Manager','Noida' from dual union all
select 13,'Global Client Services','Sw', 'UP' from dual union all
select 14,'Operations Management','All Jobs','kERALA' from dual
),
employee_xyz(person_id,name, dob, start_date, end_date, ssn) as
(
select 12,'DEAN',date'1990-01-01',date'2017-01-01',date'2017-01-20',847474 from dual union all
select 12,'DEAN',date'1990-01-01',date'2017-01-21',date'2019-03-03',847474 from dual union all
select 12,'DEAN',date'1990-01-01',date'2018-03-04',date'4712-12-31',847474 from dual
)
select distinct abc.*, xyz.name
from table_abc abc join employee_xyz xyz
on xyz.person_id = abc.emp_id_role
where trunc(sysdate) between xyz.Start_date and xyz.end_date
and person_id = 12;
EMP_ID_ROLE GROUP_NAME ROLE_NAME LOCATION_ID NAME
----------- ---------- --------------- ----------- -----
12 Insurance Manager Noida DEAN
12 Insurance Senior Manager Noida DEAN

Reconciliation Automation Query

I have one database and time to time i change some part of query as per requirement.
i want to keep record of results of both before and after result of these queries in one table and want to show queries which generate difference.
For Example,
Consider following table
emp_id country salary
---------------------
1 usa 1000
2 uk 2500
3 uk 1200
4 usa 3500
5 usa 4000
6 uk 1100
Now, my before query is :
Before Query:
select count(emp_id) as count,country from table where salary>2000 group by country;
Before Result:
count country
2 usa
1 uk
After Query:
select count(emp_id) as count,country from table where salary<2000 group by country;
After Query Result:
count country
2 uk
1 usa
My Final Result or Table I want is:
column 1 | column 2 | column 3 | column 4 |
2 usa 2 uk
1 uk 1 usa
...... but if query results are same than it shouldn't show in this table.
Thanks in advance.
I believe that you can use the same approach as here.
select t1.*, t2.* -- if you need specific columns without rn than you have to list them here
from
(
select t.*, row_number() over (order by count) rn
from
(
-- query #1
select count(emp_id) as count,country from table where salary>2000 group by country;
) t
) t1
full join
(
select t.*, row_number() over (order by count) rn
from
(
-- query #2
select count(emp_id) as count,country from table where salary<2000 group by country;
) t
) t2 on t1.rn = t2.rn

SQL: Two select statements in one query

I want to select information from two SQL tables within one query, the information is unrelated though, so no potential joints exist.
An example could be the following setup.
tblMadrid
id | name | games | goals
1 | ronaldo | 100 | 100
2 | benzema | 50 | 25
3 | bale | 75 | 50
4 | kroos | 80 | 10
tblBarcelona
id | name | games | goals
1 | neymar | 60 | 25
2 | messi | 150 | 200
3 | suarez | 80 | 80
4 | iniesta | 40 | 5
I want to have a query that gives me the following:
name | games | goals
messi | 150 | 200
ronaldo | 100 | 100
I tried to follow this logic: Multiple select statements in Single query but the following code did not work:
USE Liga_BBVA
SELECT (SELECT name,
games,
goals
FROM tblMadrid
WHERE name = 'ronaldo') AS table_a,
(SELECT name,
games,
goals
FROM tblBarcelona
WHERE name = 'messi') AS table_b
ORDER BY goals
Any advice on this one? Thanks
Info: The football stuff is just a simplifying example. In reality it is not possible to put both tables into one and have a new "team" column. The two tables have completely different structures, but I need something that matches the characteristics of this example.
You can do something like this:
(SELECT
name, games, goals
FROM tblMadrid WHERE name = 'ronaldo')
UNION
(SELECT
name, games, goals
FROM tblBarcelona WHERE name = 'messi')
ORDER BY goals;
See, for example: https://dev.mysql.com/doc/refman/5.0/en/union.html
If you like to keep records separate and not do the union.
Try query below
SELECT (SELECT name,
games,
goals
FROM tblMadrid
WHERE name = 'ronaldo') AS table_a,
(SELECT name,
games,
goals
FROM tblBarcelona
WHERE name = 'messi') AS table_b
FROM DUAL
The UNION statement is your friend:
SELECT a.playername, a.games, a.goals
FROM tblMadrid as a
WHERE a.playername = "ronaldo"
UNION
SELECT b.playername, b.games, b.goals
FROM tblBarcelona as b
WHERE b.playername = "messi"
ORDER BY goals;
You can union the queries as long as the columns match.
SELECT name,
games,
goals
FROM tblMadrid
WHERE id = 1
UNION ALL
SELECT name,
games,
goals
FROM tblBarcelona
WHERE id = 2
You can combine data from the two tables, order by goals highest first and then choose the top two like this:
MySQL
select *
from (
select * from tblMadrid
union all
select * from tblBarcelona
) alldata
order by goals desc
limit 0,2;
SQL Server
select top 2 *
from (
select * from tblMadrid
union all
select * from tblBarcelona
) alldata
order by goals desc;
If you only want Messi and Ronaldo
select * from tblBarcelona where name = 'messi'
union all
select * from tblMadrid where name = 'ronaldo'
To ensure that messi is at the top of the result, you can do something like this:
select * from (
select * from tblBarcelona where name = 'messi'
union all
select * from tblMadrid where name = 'ronaldo'
) stars
order by name;
select name, games, goals
from tblMadrid where name = 'ronaldo'
union
select name, games, goals
from tblBarcelona where name = 'messi'
ORDER BY goals
Using union will help in this case.
You can also use join on a condition that always returns true and is not related to data in these tables.See below
select tmd .name,tbc.goals from tblMadrid tmd join tblBarcelona tbc on 1=1;
join will help you even in case when tables do not have common columns
You can use UNION in this case
select id, name, games, goals from tblMadrid
union
select id, name, games, goals from tblBarcelona
you jsut have to maintain order of selected columns ie id, name, games, goals in both SQLs
as i see you want most goals in each team
you can try this
select name,games,max(goals) as 'most goals' from tblRealMadrid
union
select name,games,max(goals) as 'most goals' from tblBarcelona
In your case, the two tables have completely different structures and cannot be joined.
The UNION operator could be used. The UNION operator joins the results of two or more SELECT statements to produce a single result set. The first column in the SELECT statement is used to sort the result set.
SELECT name, games, goals
FROM tblMadrid
WHERE name = 'ronaldo'
UNION
SELECT name, games, goals
FROM tblBarcelona
WHERE name = 'messi'
ORDER BY goals;
Each SELECT statement must have the same number of columns and data types that are compatible. Also, if you want to keep the duplicates, use UNION ALL rather than UNION.

Oracle Sql : distinct value in a specific field [duplicate]

This question already has answers here:
How to select records with maximum values in two columns?
(2 answers)
Closed 7 years ago.
I have the following table :
**Country Name Number**
us John 45
us Jeff 35
fr Jean 31
it Luigi 25
fr Maxime 23
ca Justin 23
This table is order by Number. I want to have a query that for each country give me the name with highest number :
**Country Name Number**
us John 45
fr Jean 31
it Luigi 25
ca Justin 23
I try to use distinct but I can't only make it on country if I want to print the all thing...
Have an idea ?'
EDIT :
The table is obtain by a subquery
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE Countries AS
SELECT 'us' AS Country, 'John' AS Name, 45 AS "Number" FROM DUAL
UNION ALL SELECT 'us' AS Country, 'Jeff' AS Name, 35 AS "Number" FROM DUAL
UNION ALL SELECT 'fr' AS Country, 'Jean' AS Name, 31 AS "Number" FROM DUAL
UNION ALL SELECT 'it' AS Country, 'Luigi' AS Name, 25 AS "Number" FROM DUAL
UNION ALL SELECT 'fr' AS Country, 'Maxime' AS Name, 23 AS "Number" FROM DUAL
UNION ALL SELECT 'ca' AS Country, 'Justin' AS Name, 23 AS "Number" FROM DUAL;
Query 1:
SELECT Country,
MAX( Name ) KEEP ( DENSE_RANK FIRST ORDER BY "Number" DESC ) AS "Name",
MAX( "Number" ) AS "Number"
FROM Countries
GROUP BY Country
Results:
| COUNTRY | Name | Number |
|---------|--------|--------|
| ca | Justin | 23 |
| fr | Jean | 31 |
| it | Luigi | 25 |
| us | John | 45 |
I do not have an Oracle db handy but I got this working in my SQL Server db and am pretty sure it will work in Oracle (meaning I think I am using ANSI sql which should work in most db's):
SELECT m.Country,m.Name,m.number
FROM mytable m
INNER JOIN (
select country, MAX(number) as number
FROM mytable GROUP BY Country
) AS tmp ON m.Country = tmp.Country and m.Number = tmp.number
ORDER BY m.Number DESC
This has the added benefit that it should give you records when you have two people in a given country that have the same number.
You didn't give us a table name so I just called it mytable.
Try below query:
SELECT Country, MAX(numbeer) FROM Table_Name GROUP BY Country
PFB updated query to include Name:
SELECT t1.* FROM table1 t1 INNER JOIN
(SELECT country, max(numbeer) as numbeer FROM table1 GROUP BY country) t2
ON t1.country=t2.country AND t1.numbeer=t2.numbeer;
Use row_number():
select t.Country, t.Name, t.Number
from (select t.*,
row_number() over (partition by country order by number desc) as seqnum
from table t
) t
where seqnum = 1;

Select statement with multiple rows from condition on values in single column

I have the table below.Using salary as condition I want to get multiple rows.
Below is current table call it employee.
empid name salary
-----------------------------------
1 A1 alex 20000
2 B2 ben 4500
3 C1 carl 14000
compare the salary to certain fixed values, and every time the salary is larger than the fixed value, show a record in output.My attempt condition case is close to this:
incometype= case When salary<6000 then 101 When salary Between 6000 And 18000 Then
102 Else 103 End
Desired ouput would be:
empid name salary incometype
------------------------------------------
1 A1 alex 20000 101
2 A1 alex 20000 102
3 A! alex 20000 103
4 B2 ben 4500 101
5 C1 carl 14000 101
6 C1 carl 14000 102
I have tried using union but union will give me 3 rows for each record even when value meets 1st condition.
Your question is unclear, because your logic implies that you should only have 3 output rows for 3 input rows. Your output however implies that you want to compare the salary to certain fixed values, and every time the salary is larger than the fixed value, show a record in output.
If the former is the case, Minh's query is all you need. In the latter case, you can do something like this:
select e.*, m.incometype
from employee e
left join
(
select 0 as threshold, 101 as incometype
union
select 5999 as threshold, 102 as incometype
union
select 17999 as threshold, 103 as incometype
) m
on e.salary > m.threshold
order by e.empid
If you want to add a calculate column i.e. one with values calculated using columns in this query, you can simply add it as a column in the select clause, like so:
select e.*,
m.incometype,
case
when <first condition> then <business logic here>
....
else <handle default case>
end as yourcomputedcolumn
from
...
This returns 3 rows and enough for your need:
SELECT empid, name, salary,
case When salary<6000 then 101
When salary Between 6000 And 18000 Then 102
Else 103 End as incometype
FROM employee;
Not very clear on the requirement, however the following worked for me:
Select
EmpId,Name,Sal,101 IncomeType
from Emp
Union all
Select
EmpId,Name,Sal,102
from Emp
Where Sal > 6000
union all
Select
EmpId,Name,Sal,103
from Emp
Where Sal > 18000;