Oracle SQL query to pull data and add new created date column - sql

I'm quite new to Oracle SQL so please excuse me if my question actually has a relatively schoolboy answer.
So I have 2 tables, Apps and Apps_history with the definitions below.
Apps Apps_history
ID ID
Other APP_ID
DATE_MODIFIED STATUS
DATE_MODIFIED
Apps_history has app_id which is a foreign key of the primary key ID in Apps, records in Apps are frequently updated and Apps_history keeps track of this. I want a new column to show when an ID in apps was created, this can be derived from the column date_modified in Apps_History when state is equal to 'initialized'.
Currently this is what I have
select *, t.date_modified as create_date
(select app_history.date_modified
from apps
inner join app_history on
apps.id=app_history.app_id where
status='initialized') T
from apps;
But I'm getting some errors, any help to nudge me in the right direction is much appreciated,
Thanks

There are multiple ways to accomplish this. You seem to have started down the road of a correlated subquery, so to continue with that:
select a.*,
(select ah.date_modified
from app_history ah
where a.id = ah.app_id and ah.status = 'initialized')
) as created_date
from apps a;
For performance, I would recommend an index on app_history(app_id, status, date_modified).

Your subquery is not correlated. You could solve this using a correlated query as suggested by #Gordon. Also, it would throw error if you are getting multiple rows from the correlated subquery but that's fixable.
I'd use left self join for this.
select a.*,
t.date_modified as create_date
from apps a
left join apps t on a.id = t.app_id
and t.status = 'initialized';

Related

Long SQL subquery trouble

I just registered and want to ask.
I learn sql queries not so long time and I got a trouble when I decided to move a table to another database. A few articles were read about building long subqueries , but they didn't help me.
Everything works perfect before that my action.
I just moved the table and tried to rewrite the query while whole day.
update [dbo].Full
set [salary] = 1000
where [dbo].Full.id in (
select distinct k1.id
from (
select id, Topic, User
from Full
where User not in (select distinct topic_name from [DB_1].dbo.S_School)
) k1
where k1.id not in (
select distinct k2.id
from (
select id, Topic, User
from Full
where User not in (select distinct topic_name from [DB_1].dbo.Shool)
) k2,
List_School t3
where charindex (t3.NameApp, k2.Topic)>5
)
)
I moved table List_School to database [DB_1] and I can't to bend with it.
I can't write [DB_1].dbo.List_School. Should I use one more subquery?
I even thought about create a few temporary tables but it can influence on speed of execution.
Sql gurus , please invest some your time on me. Thank you in advance.
I will be happy for each hint, which you give me.
There appear to be a number of issues. You are comparing the user column to the topic_name column. An expected meaning of those column names would suggest you are not comparing the correct columns. But that is a guess.
In the final subquery you have an ansi join on table List_School but no join columns which means the join witk k2 is a cartesian product (aka cross join) which is not what you would want in most situations. Again a guess as no details of actual problem data or error messages was provided.

Issue with joins in a SQL query

SELECT
c.ConfigurationID AS RealflowID, c.companyname,
c.companyphone, c.ContactEmail, COUNT(k.caseid)
FROM
dbo.Configuration c
INNER JOIN
dbo.cases k ON k.SiteID = c.ConfigurationId
WHERE
EXISTS (SELECT * FROM dbo.RepairEstimates
WHERE caseid = k.caseid)
AND c.AccountStatus = 'Active'
AND c.domainid = 46
GROUP BY
c.configurationid,c.companyname, c.companyphone, c.ContactEmail
I have this query - I am using the configuration table to get the siteid of the cases in the cases table. And if the case exists in the repair estimates table pull the company details listed and get a count of how many cases are in the repair estimator table for that siteid.
I hope that is clear enough of a description.
But the issue here is the count is not correct with the data that is being pulled. Is there something I could do differently? Different join? Remove the exists add another join? I am not sure I have tried many different things.
Realized I was using the wrong table. The query was correct.

DB2 SQL Count across one to many relationship

I have two tables in a one to many relationship within an IBM DB2 database. I can't think of a way to describe what I'm doing in words easily so I'm linking an SQLFiddle.
Here is a working SQLFiddle on what I'm doing;
Click Here
The SQLFiddle works exactly like I need it to. My problem is, I am using an IBM DB2 database and the COUNT function does not seem to work. Does anyone have a way to return what the SQLFiddle does in a IBM DB2 compatible way?
Here is the error I get from i Navigator; Click Here
You are aggregating by the wrong column. I think this is the query you want:
SELECT Table1.quote, COUNT(Table2.quote) as TotalItem
FROM Table1 LEFT JOIN
Table2
ON Table1.quote = Table2.quote
GROUP BY Table1.quote
---------^
You need to aggregate by Table1.quote because Table2.quote might be NULL, because of the LEFT JOIN.
EDIT:
Your particular problem seems to be your having two tables with the same names. Just use column aliases:
SELECT t1.quote, COUNT(t2.quote) as TotalItem
FROM Table1 t1 LEFT JOIN
Table2 t2
ON t1.quote = t2.quote
GROUP BY t1.quote;

SQL query involving group by and joins

I couldn't be more specific in the title part but I want to do something a little bit complex for me. I thought I did it but it turned out that it is buggy.
I have three tables as following:
ProjectTable
idProject
title
idOwner
OfferTable
idOffer
idProject
idAccount
AccountTable
idAccount
Username
Now in one query I aim to list all the projects with most offers made, and in the query I also want to get details like the username of the owner, username of the offerer* etc. So I don't have to query again for each project.
Here is my broken query, it's my first experiment with GROUP BY and I probably didn't quite get it.
SELECT Project.addDate,Project.idOwner ,Account.Username,Project.idProject,
Project.Price,COUNT(Project.idProject) as offercount
FROM Project
INNER JOIN Offer
ON Project.idProject= Offer.idProject
INNER JOIN Account
ON Account.idAccount = Project.idOwner
GROUP BY Project.addDate,Project.idOwner,
Account.Username,Project.idProject,Project.Price
ORDER BY addDate DESC
*:I wrote that without thinking I was just trying to come up with example extra information, that is meaningless thanks to Hosam Aly.
Try this (modified for projects with no offers):
SELECT
Project.addDate,
Project.idOwner,
Account.Username,
Project.idProject,
Project.Price,
ISNULL(q.offercount, 0) AS offercount
FROM
(
SELECT
o.idProject,
COUNT(o.idProject) as offercount
FROM Offer o
GROUP BY o.idProject
) AS q
RIGHT JOIN Project ON Project.idProject = q.idProject
INNER JOIN Account ON Account.idAccount = Project.idOwner
ORDER BY addDate DESC
I might switch the query slightly to this:
select p.addDate,
p.idOwner,
a.Username,
p.idProject,
p.price,
o.OfferCount
from project p
left join
(
select count(*) OfferCount, idproject
from offer
group by idproject
) o
on p.idproject = o.idproject
left join account a
on p.idowner = a.idaccount
This way, you are getting the count by the projectid and not based on all of the other fields you are grouping by. I am also using a LEFT JOIN in the event the projectid or other id doesn't exist in the other tables, you will still return data.
Your question is a bit vague, but here are some pointers:
To list the projects "with most offers made", ORDER BY offercount.
You're essentially querying for projects, so you should GROUP BY Project.idProject first before the other fields.
You're querying for the number of offers made on each project, yet you ask about offer details. It doesn't really make sense (syntax-wise) to ask for the two pieces of information together. If you want to get the total number of offers, repeated in every record of the result, along with offer information, you'll have to use an inner query for that.
An inner query can be made either in the FROM clause, as suggested by other answers, or directly in the SELECT clause, like so:
SELECT Project.idProject,
(SELECT COUNT(Offer.idOffer)
FROM Offer
WHERE Offer.idProject = Project.idProject
) AS OfferCount
FROM Project

Join two tables and then pull Distinct Records

I'm writing a VS 2010 program in C# and I've ran into a SELECT statement in SQL that is taking me to long to figure out and could use some help.
Table 1 - mailfiles
id,fname,lname,etc...
Table 2 - details,
id,timestamp,page_id,mailfile_id(FK),campaign_id
I want to pull the unique/distinct mailfile_id sorted by the most current timestamp and then join them to the mailfiles table to get the rest of my info.
I had something like this,
SELECT mailfiles.id,mailfiles.fname,mailfiles.lname,mailfiles.company2,mailfiles.city,etc...
FROM mailfiles
JOIN
(SELECT DISTINCT(details.mailfile_id)
FROM details
GROUP BY details.mailfile_id) as TMP
ON mailfiles.id = TMP.mailfile_id
ORDER BY TMP.mailfile_id DESC
Which gets me the distinct/unique records but I don't have access to the details columns, which I want to display the timestamp.
Any help would be much appreciated.
Thanks
Nick
How about:
SELECT *
FROM
(SELECT mailfile_id, Max(timestamp) m_timestamp FROM details GROUP BY mailfile_id) AS latest
INNER JOIN details on latest.mailfile_id = details.mailfile_id AND latest.m_timestamp = details.timestamp
INNER JOIN mailfiles ON mailfiles.id = details.mailfile_id
ORDER BY details.timestamp
There's an unresolved ambiguity in the case that there are two identical timestamps, but it seems that's something that would have to be solved in any case. For a given id, which of these 2 timestamps is actually the latest?
I'm afraid what you want to do is quite tricky since as you've found out the distinct operator works on all the fields you list in the query. If it works for you, you could return a list of ID's using your first query and then use these ID's to retrieve the details that your require in a second query. I know its two queries, but it may end up being faster than a large complex query anyway.
SELECT MAX (timestamp), fname, lname, ...
FROM mailfiles m, details d
WHERE m.id. = d.mailfiles_id
GROUP BY m.id, fname, lname, ...
Hm - yes, I see the problem rising - do you need more than timestamp from the details? Then it get's more tricky.
SELECT m.*, d.*
FROM mailfiles m, details d
WHERE m.id = d.mailfiles_id
AND (d.mailfiles_id, d.timestamp) IN (
SELECT mailfiles_id, MAX (timestamp)
FROM details
GROUP BY mailfiles_id);
If you need details from both tables.
I don't know whether your database supports ... and (a, b) in (SELECT c, d FROM ...; postgresql does.