How can I write a query for this? I'm not an expert to write this much of complex queries in SQL. I forgot to mention bid 3, 4 here.
Based on David's query, eliminating duplicate bids and restricting by check type.
SELECT
a.bid, min(a.time) checkin, ISNULL(min(b.time), '') checkout
FROM
myTable a
LEFT JOIN
myTable b ON a.bid = b.bid
WHERE
a.type = "Check In"
AND
b.type = "Check Out"
GROUP BY
a.bid
ORDER BY
a.time
SELECT
a.bid, a.time checkin, ISNULL(b.time, '') checkout
FROM
myTable a
LEFT JOIN
myTable b ON a.bid = b.bid AND b.type = 'Check Out'
WHERE
a.type = 'Check In'
ORDER BY
a.time
EDIT
In response to your comment, seeing as there are several records of the same bid, and you only want one record per bid in your output, you need to specify which records you want in your output. When there are more than one, how do you decide what value to pick? If you always want the earliest checkin and the latest checkout, you might do something like this:
SELECT
a.bid,
MIN(a.time) checkin,
ISNULL((SELECT
MAX(time)
FROM
myTable
WHERE
bid = a.bid
AND type = 'Check Out'), '') checkout
FROM
myTable a
WHERE
a.type = 'Check In'
GROUP BY
a.bid
If that's not exactly what you want; adjust the use of MIN and MAX to fit your needs.
This will find the minimum check in and check out times for each bid id.
select bid,
(select min(time) from table b where a.bid = b.bid and type = "Check In") as CheckIn,
(select min(time) from table c where a.bid = c.bid and type = "Check Out") as CheckOut
from table c
group by c.bid
I think you're looking for something like this:
SELECT
`bid`,
MAX(IF(`type` = 'Check In', `time`, NULL)) AS `CheckIn`,
MAX(IF(`type` = 'Check Out', `time`, NULL)) AS `CheckOut`
FROM `yourtable`
GROUP BY `bid`
Related
I'm having to convert a lot of T-SQL statements this week to Oracle, most I have worked out but I'm still getting stuck on a few. The code below is one of them, I get the error that that the from clause is incorrect, I have tracked it down to this line of code:
NewBlc = Sls.CurrentBlc - SUM(NVL(Sls.NewBlc, 0) AS "New Balance",
I do not know what the correct format is to fix it. Any help appreciated.
SELECT
Sls.CustNme AS "Customer Name",
Sls.CustAddr AS "Customer Address",
Sls.CurrentBlc AS "Old Balance",
NewBlc = Sls.CurrentBlc - SUM(NVL(Sls.NewBlc, 0) AS "New Balance",
Tis
FROM
Customers,
(SELECT
c.Name AS CustNme,
c.Address AS CustAddr,
c.Balance AS CurrentBlc,
Cis(s.Item, c.Name) AS NewBlc,
Sis(c.name) AS Tis
FROM
CUST c
INNER JOIN
Sales o ON c.Name = o.cust
INNER JOIN
Purchases i on i.OrderNo = o.OrderNo
INNER JOIN
Contracters s on i.Item = s.Item
WHERE
o.Order_Date BETWEEN TO_DATE('01-01-2008', 'dd/mm/yyyy' )
AND TO_DATE('30-12-2009', 'dd/mm/yyyy')
GROUP BY
c.Name, c.Address, s.Item, c.Balance) Sls
GROUP BY
Sls.CustNme, Sls.CustAddr,Sls.CurrentBlc, NewBlc, Tis;
I'm creating a select from multiple tables using a union as I need to return a list of activities that has occurred for a particular client on the database. I need to return each union with an added column so I can tell the difference between the results. If I was to do the query in SQL it would look something like this:
SELECT cn.NoteID, cn.Note, cn.InsertedDate, 'Note Added' Notes
FROM Client c
INNER JOIN ClientNotes cn ON cn.ClientID = c.ID
WHERE c.ClientID = #ClientID
UNION
SELECT rc.ID, rc.CommNote, rc.InsertedDate, 'Communication Added' Notes
FROM ReceivedCommunication rc
LEFT JOIN Job j ON j.ID = rc.JobID
WHERE j.ClientID = #ClientID or rc.ClientID = #ClientID
My Question is how in Entity Framework using IQuerable do I return the hard-coded Notes column?
I have something like this so far:
Dim client as IQueryable(Of myresultclass) =
(From c As Client
Join cn As ClientNotes In ClientCompanyNotes On c.ID Equals cn.ClientID
Where c.ClientID = ClientID
Select cn.NoteID, cn.Note, cn.InsertedDate).Union(
From rc As ReceivedCommunication In ReceivedCommunications
Join j As Job In Jobs On j.ID Equals rc.JobID
Where j.ClientID = ClientID or rc.ClientID = ClientID
Select rc.ID, rc.CommNote, rc.InsertedDate)
Thanks for your help
Ok worked it out, should have been obvious. For anyone with the same issue, I had to update my Select from Select cn.NoteID, cn.Note, cn.InsertedDate to:
Select New myresultclass With {
.ActivityID = cn.NoteID,
.ActivityType = "Note Added"
.InsertedDate = cn.InsertedDate
}
for each one of the unions that I had
Thanks
select col_1,
col_2
from tbl_a A,
tbl_b B,
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
where A.col_1 = B.col_1
and A.col_2 = B.col_2
and (A.col_2 = B.col_2
or C.col_2 = A.col_2);
My environment is Oracle,when I run this SQL,if the sub SQL C hasn't got a result,then the entire SQL returns NULL.Whereas if C has a result(not null) which fits other condions,there could be a result.Would somebody explain why sub SQL at the from area need to be not NULL?Thanks very much.
You need to bring yourself into the 90s and start using standard joins:
select col_1,
col_2
from tbl_a A
inner join
tbl_b B
on A.col_1 = B.col_1
and A.col_2 = B.col_2
left join
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
on
C.col_2 = A.col_2
As a guess. I'm not entirely sure what your join conditions should be but that's my first attempt.
This is expected behaviour. When you join two result sets, you only want to get results where the join criteria is satisfied. If the criteria are not satisfied, you should get no results.
If I run the query "get me all the employees older than 65, and get their departments", if there are no employees older than 65, you would not expect to get any results, even if there are some departments in the database.
SELECT emp.name, dept.dept_name
FROM emp
JOIN dept
ON (emp.dept_no = dept.dept_no)
WHERE emp.age > 65;
As the others said, if you actually want to get rows regardless of whether the subquery has any results, you need to use an outer join.
I am very new at using Oracle (in the class now). I have a problem with the query I am trying to run. I have researched a lot of other answers on this site and none of them seem to apply directly to my problem so the solutions aren't working.
I need to find the total amount spent on lunches by each employee.
Show first_name, last_name, credit_limit, and total_price_spent in your results.
Order the answer by total_price_spent in descending order. Only show the employees who spent more than their credit limit.
I figured out how to do everything but the part about showing only the employees who spent more than their credit limit. I tried to use a select statement at the end but discovered that I can't use an alias in a select statement so I don't really know where to go from here. Any help would be appreciated. This is what I have so far.
select a.first_name, a.last_name, credit_limit, sum(c.quantity * d.price) as total_price_spent
from l_employees a join l_lunches b on a.employee_id = b.employee_id join l_lunch_items c on b.lunch_id = c.lunch_id join l_foods d on c.supplier_id = d.supplier_id and c.product_code = d.product_code
group by a.first_name, a.last_name, a.credit_limit
order by total_price_spent desc;
As Mike said : Add HAVING
select a.first_name, a.last_name, credit_limit, sum(c.quantity * d.price) as total_price_spent
from l_employees a join l_lunches b on a.employee_id = b.employee_id join l_lunch_items c on b.lunch_id = c.lunch_id join l_foods d on c.supplier_id = d.supplier_id and c.product_code = d.product_code
group by a.first_name, a.last_name, a.credit_limit
having sum(c.quantity * d.price) > credit_limit
order by total_price_spent desc;
I think what you're looking for is a HAVING clause. It's like a WHERE, but is used when you're using group by. You want to drop it in between the group by and order by. Something like 'HAVING total > a.credit_limit' should work. If using the alias 'total' doesn't work (haven't tested this), you might have to do 'sum(c.quantity * d.price)' again in the HAVING clause instead of using total, so HAVING sum(c.quantity * d.price) > a.credit_limit.
I have a very basic SQL query I am trying to reproduce:
SELECT t1.id, t1.name, count(*), min(t2.inserted) as inserted_first, max(t2.inserted) as inserted_last
FROM tbl1 t1
LEFT JOIN tbl2 t2 ON t1.id=t2.tbl1_id
WHERE t2.search=15
GROUP BY t1.id, t1.name
This works perfect for me. It allows me to group by the unique items of t1.id and t1.name, but also get the amount of times this pair appears, and also the min and max value of t2.inserted for the linked table. Problem is, now when I turn this into LINQ I get:
Dim query =
From t1 In ent.TBL1
Join t2 In ent.TBL2 On t1.id Equals t2.tbl1_id
Where (t2.search=15)
Group t1 By t1.id, t1.name Into Group
Select New With {
.id = id,
.name = name,
.count = Group.Count,
.min_value = ???,
.max_Value = ???
}
I am lost as to what i can do to select the min and max. Group.Min would work if it was of the same table as the grouping, however since it is in t2, I am not able to reference it. Also I can not add it to my group by, since its different.
Note that tbl2 links to tbl1 on tbl2.tbl1_id -> tbl1.id. Also this is a dumbed down example of my problem, not the real live schema.
I appreciate any help on this matter
I'm not a VB person, but I think you want:
Group t1, t2 By t1.id, t1.name Into Group
Select New With {
.id = id,
.name = name,
.count = Group.Count,
.min_value = Group.Min(Function(x) x.t2.Inserted),
.max_Value = Group.Max(Function(x) x.t2.Inserted)
}
Note how here each group element contains both t1 and t2, which is how you're able to get to the Inserted property. It's not actually clear whether you even need t1 or any other parts of t2, so you may be able to use:
Group t2.Inserted By t1.id, t1.name Into Group
Select New With {
.id = id,
.name = name,
.count = Group.Count,
.min_value = Group.Min(),
.max_Value = Group.Max()
}
Unfortunately my VB LINQ skills aren't up to the challenge of knowing whether that's right for you. If you'd be happy with it in C# (which you could then convert) I could help you more easily...