Second table columns inner join [duplicate] - sql

This question already has answers here:
In Oracle "AS" alias not working
(3 answers)
SQL syntax or database constrictions?
(1 answer)
Closed 4 years ago.
I am not able to select columns as I am getting SQL command not properly ended error
(
select mobile_no,SIM_NO,START_DATE,END_DATE
from (
select mobile_no,SIM_NO,START_DATE,END_DATE
from employee_1
) myemployee
) join (
( select mobile_1.mobile_no,mobile_1.status
from mobile_1
) as mymobile ) on myemployee.mobile_no = mymobile.mobile_no
Thanks in advance. If this is work i will apply it in my project.

This one might be better:
SELECT mobile_no,
sim_no,
start_date,
end_date
FROM (SELECT mobile_no,
sim_no,
start_date,
end_date
FROM employee_1) myemployee
JOIN
(SELECT mobile_1.mobile_no, mobile_1.status FROM mobile_1) mymobile
ON myemployee.mobile_no = mymobile.mobile_no;
[EDIT, based on a_horse's comment]
SELECT e.mobile_no,
e.sim_no,
e.start_date,
e.end_date
FROM employee_1 e JOIN mobile_1 m ON m.mobile_no = e.mobile_no

Related

Column name is invalid while using SQL joins [duplicate]

This question already has answers here:
Invalid column name error in WHERE clause, column selected with CASE
(4 answers)
Closed 2 years ago.
I came across a problem that I do not understand.
SELECT T1.CUSTOMER_ID,CONVERT(DATE,T1.DOB,105) [DATE_OF_BIRTH],
T2.TOTAL_AMT,
DATEDIFF(YEAR,CONVERT(DATE,T1.DOB,105), GETDATE()) as AGE
FROM CUSTOMER T1
INNER JOIN TRANSACTIONS T2 ON T1.CUSTOMER_ID=T2.CUST_ID
WHERE AGE>=25 and AGE <=35
Whenever I run this query it gives an error:
age is an invalid column
I am trying to find out those customers whose age lies between 25 to 35.
In your query, Age doesn't exist yet, since WHERE is evaluated before the SELECT list.
Use a derived table:
select * from
(
SELECT T1.CUSTOMER_ID,CONVERT(DATE,T1.DOB,105) [DATE_OF_BIRTH],
T2.TOTAL_AMT,
DATEDIFF(YEAR,CONVERT(DATE,T1.DOB,105), GETDATE()) as AGE
FROM CUSTOMER T1
INNER JOIN TRANSACTIONS T2 ON T1.CUSTOMER_ID=T2.CUST_ID
) dt
WHERE AGE>=25 and AGE <=35
Have you heard about logical query processing?
SELECT T1.CUSTOMER_ID,CONVERT(DATE,T1.DOB,105) [DATE_OF_BIRTH],
T2.TOTAL_AMT,
DATEDIFF(YEAR,CONVERT(DATE,T1.DOB,105), GETDATE()) as AGE
FROM CUSTOMER T1
INNER JOIN TRANSACTIONS T2 ON T1.CUSTOMER_ID=T2.CUST_ID
WHERE DATEDIFF(YEAR,CONVERT(DATE,T1.DOB,105), GETDATE()) >=25 and
DATEDIFF(YEAR,CONVERT(DATE,T1.DOB,105), GETDATE()) <= 35

Oracle SQL: Get the max record for each duplicate ID in self join table [duplicate]

This question already has answers here:
Fetch the rows which have the Max value for a column for each distinct value of another column
(35 answers)
GROUP BY with MAX(DATE) [duplicate]
(6 answers)
Oracle SQL query: Retrieve latest values per group based on time [duplicate]
(2 answers)
Closed 5 years ago.
It's been marked as a duplicate and seems to be explained a bit in the linked questions, but I'm still trying to get the separate DEBIT and CREDIT columns on the same row.
I've created a View and I am currently self joining it. I'm trying to get the max Header_ID for each date.
My SQL is currently:
SELECT DISTINCT
TAB1.id,
TAB1.glperiods_id,
MAX(TAB2.HEADER_ID),
TAB1.batch_date,
TAB1.debit,
TAB2.credit,
TAB1.descrip
FROM
IQMS.V_TEST_GLBATCH_GJ TAB1
LEFT OUTER JOIN
IQMS.V_TEST_GLBATCH_GJ TAB2
ON
TAB1.ID = TAB2.ID AND TAB1.BATCH_DATE = TAB2.BATCH_DATE AND TAB1.GLPERIODS_ID = TAB2.GLPERIODS_ID AND TAB1.DESCRIP = TAB2.DESCRIP AND TAB1.DEBIT <> TAB2.CREDIT
WHERE
TAB1.ACCT = '3648-00-0'
AND
TAB1.DESCRIP NOT LIKE '%INV%'
AND TAB1.DEBIT IS NOT NULL
GROUP BY
TAB1.id,
TAB1.glperiods_id,
TAB1.batch_date,
TAB1.debit,
TAB2.credit,
TAB1.descrip
ORDER BY TAB1.batch_date
And the output for this is (37 rows in total):
I'm joining the table onto itself to get DEBIT and CREDIT on the same line. How do I select only the rows with the max HEADER_ID per BATCH_DATE ?
Update
For #sagi
Those highlighted with the red box are the rows I want and the ones in blue would be the ones I'm filtering out.
Fixed mistake
I recently noticed I had joined my table onto itself without making sure TAB2 ACCT='3648-00-0'.
The corrected SQL is here:
SELECT DISTINCT
TAB1.id,
TAB1.glperiods_id,
Tab1.HEADER_ID,
TAB1.batch_date,
TAB1.debit,
TAB2.credit,
TAB1.descrip
FROM
IQMS.V_TEST_GLBATCH_GJ TAB1
LEFT OUTER JOIN
IQMS.V_TEST_GLBATCH_GJ TAB2
ON
TAB1.ID = TAB2.ID AND TAB1.BATCH_DATE = TAB2.BATCH_DATE AND TAB2.ACCT ='3648-00-0'AND TAB1.GLPERIODS_ID = TAB2.GLPERIODS_ID AND TAB1.DESCRIP = TAB2.DESCRIP AND TAB1.DEBIT <> TAB2.CREDIT
WHERE
TAB1.ACCT = '3648-00-0'
AND
TAB1.DESCRIP NOT LIKE '%INV%'
AND TAB1.DEBIT IS NOT NULL
ORDER BY TAB1.BATCH_DATE
Use window function like ROW_NUMBER() :
SELECT s.* FROM (
SELECT t.*,
ROW_NUMBER() OVER(PARTITION BY t.batch_id ORDER BY t.header_id DESC) as rnk
FROM YourTable t
WHERE t.ACCT = '3648-00-0'
AND t.DESCRIP NOT LIKE '%INV%'
AND t.DEBIT IS NOT NULL) s
WHERE s.rnk = 1
This is an analytic function that rank your record by the values provided in the OVER clause.
PARTITION - is the group
ORDER BY - Who's the first of this group (first gets 1, second 2, ETC)
It is a lot more efficient then joins(Your problem could have been solved in many ways) , and uses the table only once.

Select 0 sum for empty years

this seems to be a very common question and yet I can't seem to find an answer that easily transitions into my issue. Typically people are looking for a 0 for missing months, mine is with years. I'm just looking for each product that has been sold in the last 10 years to show for those 10 years the amount or a 0 if none.
My code that shows years where there have been sales:
select upper(_producttype) as _product, YEAR(_date) as _year,
coalesce(SUM(s._quantity * pu._usdperunit),0) as _profit
from QualityControl.dbo._Shipment s
join QualityControl.dbo._ProductUnits pu
on pu._prodid = s._productid
where year(GETDATE())-YEAR(_date) < 11
and upper(_producttype) != 'EQUIPMENT'
group by YEAR(_date), _producttype
order by _producttype, YEAR(_date)
My query that gives me a list of the last 10 years (+ current):
select distinct YEAR(_date) as _year
from QualityControl.dbo._Shipment s
where year(GETDATE())-YEAR(_date) < 11
and _producttype != 'Equipment'
order by YEAR(_date)
I have tried a union with _profit being 0. I have tried a cross join, but seemed to be getting too many columns at that point. Any help at this point would be much appreciated.
Thank you.
Without changing your queries you can do following with them.
Just put your grouped data in one CTE
years in another
create third subset that's combination of distinct products and years
LEFT JOIN between combinations and your data
.
WITH CTE_Data AS
(
select upper(_producttype) as _product, YEAR(_date) as _year,
coalesce(SUM(s._quantity * pu._usdperunit),0) as _profit
from QualityControl.dbo._Shipment s
join QualityControl.dbo._ProductUnits pu
on pu._prodid = s._productid
where year(GETDATE())-YEAR(_date) < 11
and upper(_producttype) != 'EQUIPMENT'
group by YEAR(_date), _producttype
)
, CTE_Years AS
(
select distinct YEAR(_date) as _year
from QualityControl.dbo._Shipment s
where year(GETDATE())-YEAR(_date) < 11
and _producttype != 'Equipment'
)
, CTE_AllCombo AS
(
SELECT DISTINCT y._year, d._Product
FROM CTE_Years y
CROSS JOIN CTE_Data d
)
SELECT c._year, c._product, COALESCE(d._profit, 0) AS _profit
FROM CTE_AllCombo c
LEFT JOIN CTE_Data d ON d._year = c._year and d._product = c._product

No rows fetching but need a value [duplicate]

This question already has answers here:
How to return a default value when no rows are returned from the select statement
(7 answers)
Closed 8 years ago.
I need some help with the following query.
Select date, Source,count(*) as TOTALCOUNT
from Table A
where date = '2014-10-15' and Source = 'EMAIL'
group by date,source
There is no EMAIL source for a particular day. So, it gives no rows.
But I want to get 0 in Totalcount even if EMAIL is not there for that day but can present next day.
It should be like,
Date,Source, Totalcount
15/10/14,Email,0
I used ISNULL function not working as no rows has been resulted.
You could perform a join with a "constant" query. It's an ugly hack, but it should do the trick:
SELECT c.date, c.source, COALESCE(totalcount, 0)
FROM (SELECT '2014-10-15' AS date, 'EMAIL' AS source) c
LEFT JOIN (SELECT date, source, COUNT(*) AS totalcount
FROM a
GROUP BY date, source) a
ON a.date = c.date AND a.source = c.source

Grouping two dates as one in Oracle-SQL

I have a table 'task' with three relevant fields: date_created, date_updated, and is_closed.
I have a simple query that counts the number of tasks created:
SELECT task.date_created, count(task.is_closed)
FROM task
GROUP BY task.date_created
ORDER BY task.date_created
What I'd like is to also have the number of tasks closed per day. For our purposes, a task's final updated date is when is_closed='true'
So, the final table should look like
date opened closed
04/01/13 8 6
04/02/13 9 5
I think you need to do this as two subqueries. Here is one approach, using full outer join:
select coalesce(a.date_created, c.date_updated) as thedate,
coalesce(a.opened, 0) as opened,
coalesce(c.closed, 0) as closed
from (select date_created, count(*) as opened
from task
group by date_created
) a full outer join
(select date_updated, count(*) as closed
from task
where is_closed = 1 -- or whatever the value is
group by date_updated
) c
on a.date_created = c.date_updated
The full outer join guarantees that all dates are present, even when you have only closes or opens.
You can use a CASE statement with your COUNT:
SELECT task.date_created,
count(1) opened,
count(case when is_closed = 'true' then 1 end) closed
FROM task
GROUP BY task.date_created
ORDER BY task.date_created
SQL Fiddle Demo
Given your comments, here is an approach using a couple Common Table Expressions:
WITH OPENED AS (
SELECT date_created, count(1) opened
FROM task
GROUP BY date_created
) ,
CLOSED AS (
SELECT date_updated, count(1) closed
FROM task
WHERE is_closed = 'true'
GROUP BY date_updated
)
SELECT D.YourDateField, o.opened, c.closed
FROM YourDateTable D
LEFT JOIN Opened O ON D.YourDateField = O.Date_Created
LEFT JOIN CLosed C ON D.YourDateField = C.Date_Created
As Gordon points out, a FULL OUTER JOIN would also work. I just prefer using a dates table to seed from. Create the table once, and use it wherever you may need to.