why sqlite returns row counts of while Join - sql

sqlite returns row count while executing this query
SELECT sum(s.Card_10) ,sum(p.Card_10) FROM Sales_Table s , Purchase_Table p
ANSWER
is sum(s.Card_10) 4 and sum(card_10) is 40
but if any execute these queries separately it reruns correct answer
Select sum(Card_10) from sales_table
Answer
1
and
Select sum(Card_10) from Purchase_table
Answer
40
why the error happen in such type of JOINS ?

In the query
SELECT sum(s.Card_10) ,sum(p.Card_10) FROM Sales_Table s , Purchase_Table p
a cross join of sales_table and purchase_table would be performed. So if sales_table has 1 row with card_10 column value of 1 and purchase_table has 4 rows with different values of card_10 that sum up to 40.
So the cross join (with some dummy data) would look like
s.card_10 p.card_10
1 5
1 10
1 8
1 17
Hence you get the incorrect result.
One way of getting the correct counts in a single query is to use union.
select sum(Card_10) from sales_table
union all
select sum(Card_10) from Purachase_table
or
select max(fromsalestable) as fromsalestable, max(frompurchasetable) as frompurchasetable
from
(
select sum(Card_10) as fromsalestable, null as frompurchasetable from sales_table
union all
select null, sum(Card_10) from Purachase_table
) t

Related

How to join 2 queries with different number of records and columns in oracle sql?

I have three tables:
Employee_leave(EmployeeID,Time_Period,leave_type)
Employee(EID,Department,Designation)
leave_eligibility(Department,Designation, LeaveType, LeavesBalance).
I want to fetch the number of leaves availed by a particular employee in each LeaveTypes(Category) so I wrote following query Query1
SELECT LEAVE_TYPE, SUM(TIME_PERIOD)
FROM EMPLOYEE_LEAVE
WHERE EMPLOYEEID=78
GROUP BY LEAVE_TYPE
order by leave_type;
output for Query1
Leave_Type | SUM(Time_Period)
Casual 1
Paid 4
Sick 1
I want to fetch the number of leaves an employee is eligible for each leave_type(category). Following query Query2 gives the desire result.
Select UNIQUE Leavetype,LEAVEBALANCE
from LEAVE_ELIGIBILITY
INNER JOIN EMPLOYEE
ON LEAVE_ELIGIBILITY.DEPARTMENT= EMPLOYEE.DEPARTMENT
AND LEAVE_ELIGIBILITY.DESIGNATION= EMPLOYEE.DESIGNATION
WHERE EID=78
order by leavetype;
output for Query2
LeaveType | LeaveBalance
Casual 10
Paid 15
Privlage 6
Sick 20
Now I want to join these 2 queries Query1 and Query2 or create view which displays records from both queries. Also as you can see from output there are different no. of records from different queries. For a record which is not present in output of query1, it should display 0 in final output. Like in present case there is no record in output of query1 like privlage but it should display 0 in Sum(time_period) in Privlage of final output. I tried creating views of these 2 queries and then joining them, but I'm unable to run final query.
Code for View 1
create or replace view combo_table1 as
Select UNIQUE Leavetype,LEAVEBALANCE,EMPLOYEE.DEPARTMENT,EMPLOYEE.DESIGNATION, EID
from LEAVE_ELIGIBILITY
INNER JOIN EMPLOYEE
ON LEAVE_ELIGIBILITY.DEPARTMENT= EMPLOYEE.DEPARTMENT
AND LEAVE_ELIGIBILITY.DESIGNATION= EMPLOYEE.DESIGNATION
WHERE EID='78';
Code for View 2
create or replace view combo_table2 as
SELECT LEAVE_TYPE, SUM(TIME_PERIOD) AS Leave_Availed
FROM EMPLOYEE_LEAVE
WHERE EMPLOYEEID='78'
GROUP BY LEAVE_TYPE;
Code for joining 2 views
SELECT combo_table1.Leavetype, combo_table1.LEAVEBALANCE, combo_table2.leave_availed
FROM combo_table1 v1
INNER JOIN combo_table2 v2
ON v1.Leavetype = v2.LEAVE_TYPE;
But I'm getting "%s: invalid identifier" while executing the above query. Also I know I can't use union as it requires same column which here it is not.
I'm using Oracle 11g, so please answer accordingly.
Thanks in advance.
Desired final output
LeaveType | LeaveBalance | Sum(Time_period)
Casual 10 1
Paid 15 4
Privlage 6 0
Sick 20 1
To get the final desired output ...
"For a record which is not present in output of query1, it should display 0 in final output. "
... use an outer join to tie the taken leave records to the other tables. This will give zero time_duration for leave types which the employee has not taken.
select emp.Employee_ID
, le.leavetype
, le.leavebalance
, sum (el.Time_Duration) as total_Time_Duration
from employee emp
inner join leave_eligibility le
on le.department= emp.department
and le.designation= emp.designation
left outer join Employee_leave el
on el.EmployeeID = emp.Employee_ID
and el.leave_type = le.leavetype
group by emp.Employee_ID
, le.leavetype
, le.leavebalance
;
Your immediate problem:
I'm getting "%s: invalid identifier"
Your view has references to a column EID although none of your posted tables have a column of that name. Likewise there is confusion between Time_Duration and time_period.
More generally, you will find life considerably easier if you use the exact same name for common columns (i.e. consistently use either employee_id or employeeid, don't chop and change).
Try this examle:
with t as (
select 'Casual' as Leave_Type, 1 as Time_Period, 0 as LeaveBalance from dual
union all
select 'Paid', 4,0 from dual
union all
select 'Sick', 1,0 from dual),
t1 as (
select 'Casual' as Leave_Type, 0 as Time_Period, 10 as LeaveBalance from dual
union all
select 'Paid', 0, 15 from dual
union all
select 'Privlage', 0, 6 from dual
union all
select 'Sick', 0, 20 from dual)
select Leave_Type, sum(Time_Period), sum(LeaveBalance)
from(
select *
from t
UNION ALL
select * from t1
)
group by Leave_Type
Ok, edit:
create or replace view combo_table1 as
Select UNIQUE Leavetype, 0 AS Leave_Availed, LEAVEBALANCE
from LEAVE_ELIGIBILITY INNER JOIN EMPLOYEE ON LEAVE_ELIGIBILITY.DEPARTMENT= EMPLOYEE.DEPARTMENT AND LEAVE_ELIGIBILITY.DESIGNATION= EMPLOYEE.DESIGNATION
WHERE EID='78';
create or replace view combo_table2 as
SELECT LEAVE_TYPE as Leavetype, SUM(TIME_PERIOD) AS Leave_Availed, 0 as LEAVEBALANCE
FROM EMPLOYEE_LEAVE
WHERE EMPLOYEEID='78'
GROUP BY LEAVE_TYPE, LEAVEBALANCE;
SELECT Leavetype, sum(LEAVEBALANCE), sum(leave_availed)
FROM (
select *
from combo_table1
UNION ALL
select * from combo_table2
)
group by Leavetype;

How to write a LEFT JOIN in BigQuery's Standard SQL?

We have a query that works in BigQuery's Legacy SQL. How do we write it in Standard SQL so it works?
SELECT Hour, Average, L.Key AS Key FROM
(SELECT 1 AS Key, *
FROM test.table_L AS L)
LEFT JOIN
(SELECT 1 AS Key, Avg(Total) AS Average
FROM test.table_R) AS R
ON L.Key = R.Key ORDER BY Hour ASC
Currently the error it gives is:
Equality is not defined for arguments of type ARRAY<INT64> at [4:74]
BigQuery has two modes for queries: Legacy SQL and Standard SQL. We have looked at the BigQuery Standard SQL documentation and also see just one SO answer on Standard SQL joins in BigQuery - but so far, it is unclear to us what the key change needed might be.
Table_L looks like this:
Row Hour
1 A
2 B
3 C
Table_R looks like this:
Row Value
1 10
2 20
3 30
Results Desired:
Row Hour Average(OfR) Key
1 A 20 1
2 B 20 1
3 C 20 1
How do we rewrite this BigQuery Legacy SQL query to work in Standard SQL?
Based on your recent update in question and comments - try below
WITH Table_L AS (
SELECT 1 AS Row, 'A' AS Hour UNION ALL
SELECT 2 AS Row, 'B' AS Hour UNION ALL
SELECT 3 AS Row, 'C' AS Hour
),
Table_R AS (
SELECT 1 AS Row, 10 AS Value UNION ALL
SELECT 2 AS Row, 20 AS Value UNION ALL
SELECT 3 AS Row, 30 AS Value
)
SELECT
Row,
Hour,
(SELECT AVG(Value) FROM Table_R) AS AverageOfR,
1 AS Key
FROM Table_L
Above is for testing
the query you should run in "production" is
SELECT
Row,
Hour,
(SELECT AVG(Value) FROM Table_R) AS AverageOfR,
1 AS Key
FROM Table_L
In case, if for some reason you are bound to JOIN, use below CROSS JOIN version
SELECT
Row,
Hour,
AverageOfR,
1 AS Key
FROM Table_L
CROSS JOIN ((SELECT AVG(Value) AS AverageOfR FROM Table_R))
or below LEFT JOIN version with Key field involved (in case if Key really important for your logic - which somehow I feel is true)
SELECT
Row,
Hour,
AverageOfR,
L.Key AS Key
FROM (SELECT 1 AS Key, Row, Hour FROM Table_L) AS L
LEFT JOIN ((SELECT 1 AS Key, AVG(Value) AS AverageOfR FROM Table_R)) AS R
ON L.Key = R.Key
Your error message suggests that key is not a column in table_L. If no, then don't include it in the query.
It looks like you simply want the average of the total from table_R. You can approach this as:
SELECT l.*, r.average
FROM test.table_L as l CROSS JOIN
(SELECT Avg(Total) as average
FROM test.table_R
) R
ORDER BY l.hour ASC;

How to get a correlated subquery as column

I dont know how I can do this sql query, probably its simple but I don't know how i can do it.
I have 2 tables:
Table_Articles:
COD NAME
1 Bottle
2 Car
3 Phone
Table_Articles_Registered
COD_ARTICLE DATE
1 05/11/2014
1 06/11/2014
1 07/11/2014
2 08/11/2014
2 09/11/2014
3 05/11/2014
I want take in the table Table_Articles_Registered the row with the MAX date , finally I want get this result:
COD NAME DATE
1 Bottle 07/11/2014
2 Car 09/11/2014
3 Phone 05/11/2014
I need use the sencente like this. The problem its in the subquery. Later I use other inner join in the sentence, this is only a fragment.
select
_Article.Code,
_Article.Description ,
from Tbl_Articles as _Article left join
(
select top 1 *
from ArticlesRegisterds where DATE_REGISTERED <= '18/11/2014'
order by DATE_REGISTERED
)
as regAux
on regAux.CODE_ARTICLE= _Article.CODE
I dont know how can I connect the field CODE_ARTICLE in the table ArticlesRegisterds with the first query.
I think this is a basic aggregation query with a join:
select a.cod, a.name, max(ar.date) as date
from Artiles a join
ArticlesRegisterds ar
on ar.cod_article = a.cod
group by a.cod, a.name
Try this:-
SELECT TAR.COD_ARTICLE, TA.NAME, MAX(TAR.DATE)
FROM Table_Articles_Registered TAR JOIN
Table_Articles.TA ON TAR.COD_ARTICLE = TA.COD
GROUP BY TAR.COD_ARTICLE, TA.NAME;
Can't you just do this?:
SELECT
Table_Articles.COD,
Table_Articles.NAME,
(
SELECT MAX(Table_Articles_Registered.DATE)
FROM Table_Articles_Registered
WHERE Table_Articles.COD_ARTICLE=Table_Articles.COD
) AS DATE
FROM
Table_Articles

Grouping in SQL Statement

I have the following SQL statement:
SELECT TOP 30
a.ClassAdID, -- 0
a.AdTitle, -- 1
a.ClassAdCatID, -- 2
b.ClassAdCat, -- 3
a.Img1, -- 4
e.Domain, -- 5
a.AdText, -- 6
a.RegionID, -- 7
a.IsEvent, -- 8
a.IsCoupon, -- 9
b.ParentID, -- 10
a.MemberID, -- 11
a.AdURL, -- 12
a.Location, -- 13
a.GroupID -- 14
FROM ClassAd a
INNER JOIN ClassAdCat b ON b.ClassAdCatID = a.ClassAdCatID
INNER JOIN Member d ON d.MemberID = a.MemberID
INNER JOIN Region e ON e.RegionID = a.RegionID
WHERE DATEDIFF(d, GETDATE(), a.ExpirationDate) >= 0
AND PostType <> 'CPN'
ORDER BY a.CreateDate DESC
I want to only show one from each GROUPID... How can I adjust the statement to achieve this as I am lost with DISTINCT, GROUP BY etc..
Any help would be appreciated.
Many thanks,
Paul
You can use ROW_NUMBER function to partition data set based on GroupId values thus: for every new GroupId values the counter is restarted from 1 and the first row (with ROW_NUMBER = 1) is the newest record (a.CreateDate DESC). Then, we filter all records having ROW_NUMBER = 1 .
SELECT TOP 30 *
FROM
(
SELECT
a.ClassAdID, -- 0
a.AdTitle, -- 1
a.ClassAdCatID, -- 2
b.ClassAdCat, -- 3
a.Img1, -- 4
e.Domain, -- 5
a.AdText, -- 6
a.RegionID, -- 7
a.IsEvent, -- 8
a.IsCoupon, -- 9
b.ParentID, -- 10
a.MemberID, -- 11
a.AdURL, -- 12
a.Location, -- 13
a.GroupID, -- 14
ROW_NUMBER() OVER(PARTITION BY a.GroupId ORDER BY a.CreateDate DESC) AS PseudoId
FROM ClassAd a
INNER JOIN ClassAdCat b ON b.ClassAdCatID = a.ClassAdCatID
INNER JOIN Member d ON d.MemberID = a.MemberID
INNER JOIN Region e ON e.RegionID = a.RegionID
WHERE DATEDIFF(d, GETDATE(), a.ExpirationDate) >= 0
AND PostType <> 'CPN'
) q
WHERE q.PseudoId = 1;
GROUP BY goes with an AGGREGATE function... meaning you want to add up the values in the group, or find the biggest, or smallest in the group etc.
DISTINCT will remove duplicate rows.
in your query, you may be getting a bunch of not-so-similar rows that all happen to have the same group_id... if this is so, then you need to decide which one of those rows you really want to see.
maybe you want the newest one, or the one with the longest name, or something like that.
for grouping, you would pick a column like createdon and say something like MAX( createdon ) in the select list, then group on every other column in the select list to find the rows that match each other (except for created on), and return that only once with the largest value for created on... hope that makes sense.
edit:
very simple example for group id and create date. ( you can keep adding more columns as needed - one in the group by list for every one in the select list :
SELECT groupid, max( createdate )
FROM ClassAd
GROUP BY groupId
If I understand correctly you want to get one row from each group (like groupid)
I used sql server 2005 (Nothwind)
SELECT TOP 30 Customers.CompanyName, Orders.ShipCity, Orders.Freight
FROM Customers INNER JOIN
Orders ON Customers.CustomerID = Orders.CustomerID
GROUP BY Customers.CompanyName, Orders.ShipCity, Orders.Freight

help in sql count

Suppose I have a table with 2 columns (status and date) like the following:
status: U T U U L
date: 12 14 15 16 17
Can I (using only 1 SQL statement) count the number of distinct values in the status? That is:
count(U)=3
count(T)=1
count(L)=2
count(P)=0
Can I do this with 1 SQL query?
Note: I have static values in status. I can only have (U-T-L-P)
You need to use Group By:
SELECT Status, Count(Status)
FROM table
GROUP BY Status
This will not return P = 0 if P is not populated in the table. In your application logic you will need to check and if a certain status is not returned, it means there are no entries (i.e. 0).
SQL cannot query records that are not there.
This will return a row for every status and the count in the second column:
SELECT Status, COUNT(*) Cnt
FROM Tbl
GROUP BY Status
So it would return
Status Cnt
U 3
T 1
L 1
for your example (in no defined order). Use ORDER BY if you want to sort the results.
You can do this with a query which groups on your status column, e.g.
SELECT COUNT(*) as StatusCount, Status
FROM MyTable
GROUP BY Status
To get the zero for the status P, you have to do some devious stuff using a table that lists all the possible statuses.
SELECT COUNT(A.Status), B.Status
FROM AnonymousTable AS A RIGHT OUTER JOIN
(SELECT 'P' AS Status FROM Dual
UNION
SELECT 'U' AS Status FROM Dual
UNION
SELECT 'L' AS Status FROM Dual
UNION
SELECT 'T' AS Status FROM Dual
) AS B ON A.Status = B.Status
GROUP BY B.Status;
The 4-way UNION is one way of generating a list of values; your DBMS may provide more compact alternatives. I'm assuming that the table Dual contains just one row (as found in Oracle).
The COUNT(A.Status) counts the number of non-null values in A.Status. The RIGHT OUTER JOIN lists the row from B with Status = 'P' and joins it with a single NULL for the A.Status, which the COUNT(A.Status) therefore counts as zero. If you used COUNT(*), you'd get a 1 for the count.