How to combine these two SELECT statment into one - sql

I have two SELECT query which are written in MySQL
$sql = 'SELECT Name FROM category WHERE CategoryID = '.$id;
AND
$sql = "SELECT * FROM sub_category WHERE ParentID = $id ORDER BY OrderIndex";
So far I have to translate these two query to Oracle PL/SQL‚I came in idea to combine these two statment into one and so far I write query but I am a little bit confusing since I am begginer in PL/SQL
SELECT
c.Name,
sc.Name as SubCategoryName,
sc.ID as SubCategoryID,
sc.Picture as Picture,
sc.OrderIndex
FROM Category c
INNER JOIN sub_category sc ON ParentID =
WHERE CategoryID = 23;
Here is graphical representation of tables
CategoryTable
SubcategoryTable

Your idea is correct, joining tables is one of the standard ways to "combine two select statements together".
You are going to get different results depending on the kind of join you use.
See for instance this question for an explanation of the different kind of joins.
Your query is almost correct (assuming you want an inner join), you are missing the right hand side on the join condition:
SELECT
c.Name,
sc.Name as SubCategoryName,
sc.ID as SubCategoryID,
sc.Picture as Picture,
sc.OrderIndex
FROM Category c
INNER JOIN sub_category sc ON sc.ParentID = c.CategoryID
WHERE CategoryID = 23;

Your select is close to be working, you forgot to connect joined tables on their column which will result in error and there is no need to use inner as inner join = join. More useful information on joins can be found here https://www.techonthenet.com/oracle/joins.php
This should work for you:
SELECT c.name,
sc.name subcategoryname,
sc.id subcategoryid,
sc.picture picture,
sc.orderindex
FROM category c
JOIN sub_category sc
ON sc.parentid = c.categoryid
WHERE c.categoryid = 23;

Related

SQL Inner Join Issue/Alternative Join

I'm trying to correct this query where I need to join the table capcase first and then join table called capstatus second.There are different tables from capcase status and capcaseservicesprovidedstatus where foreign keys can be seen and I need to join the correct tables. I'm wondering if maybe I need to use a join other than an 'inner join' to accomplish this task or confirm what I'm doing wrong with my query as the last two lines are the ones I believe are issue. Any help is appreciated, thank you in advance.
SELECT family.Id as Family_ID, person.firstName + ' ' + person.lastName as Name, capcaseServicesProvided.idperson as Person_ID,capcaseservicesProvided.idCase as Case_ID, capcaseServicesProvided.Id as Service_ID,capStatus.Status as Case_Status, capServices.Service, capStatusService.ServiceStatus as Service_Status,
capcaseServicesProvided.Qty, capServicesUnit.Unit, capcaseServicesProvided.Date as Service_Date, capCase.DateApplied as Case_Date
FROM capcaseServicesProvided
INNER JOIN person on capcaseServicesProvided.idperson = person.Id
INNER JOIN capServices on capcaseServicesProvided.idService = capServices.Id
INNER JOIN capServicesUnit on capcaseServicesProvided.Unit = capServicesUnit.Id
INNER JOIN capStatusService on capcaseServicesProvided.Status = capStatusService.Id
INNER JOIN family on person.idFamily = family.Id
INNER JOIN capStatus on capcaseServicesProvided.Status= capStatus.Id
INNER JOIN capCase on capCaseServicesProvided.Date = capCase.DateApplied;
I would like to suggest an approach rather than attempt a specific solution. Note we know absolutely nothing about your tables or their design so asking us to understand either requires quite a bit of information, so ultimately it is better for you to learn about JOINS and/or how to solve such dilemmas yourself.
I suggest you reduce the size of the initial query to the ABSOLUTE MINIMUM which looks (I think) like this:
SELECT
family.Id AS Family_ID
, person.firstName + ' ' + person.lastName AS Name
, capcaseServicesProvided.idperson AS Person_ID
, capcaseservicesProvided.idCase AS Case_ID
, capcaseServicesProvided.Id AS Service_ID
FROM capcaseServicesProvided
INNER JOIN person ON capcaseServicesProvided.idperson = person.Id
INNER JOIN family ON person.idFamily = family.Id
;
Now assuming the minimum query is correct, try joining ONE EXTRA TABLE and including the columns needed from it into the select clause. Start by adding the extra table using an INNER JOIN. If you notice that some rows you want disappear change that to a LEFT JOIN
e.g.
SELECT
family.Id AS Family_ID
, person.firstName + ' ' + person.lastName AS Name
, capcaseServicesProvided.idperson AS Person_ID
, capcaseservicesProvided.idCase AS Case_ID
, capcaseServicesProvided.Id AS Service_ID
, capServices.Service
FROM capcaseServicesProvided
INNER JOIN person ON capcaseServicesProvided.idperson = person.Id
INNER JOIN family ON person.idFamily = family.Id
INNER JOIN capServices ON capcaseServicesProvided.idService = capServices.Id
-- or if needed --LEFT JOIN capServices ON capcaseServicesProvided.idService = capServices.Id
;
Keep repeating this cycle until you have joined all the needed tables.
I suspect you just need one or more LEFT JOINS but without sample data from each table and DDL for each table it is really hard to tell you which tables need these.

SQL Query between three tables, get data only from one table

I have these 3 tables:
product table
id
siteId
optionsSet table
id
productId
...
option table
id
optionsSetId
code
...
Question:
How can I make a SQL query to select all from option table by knowing these two: option.code and product.siteId ?
I know how to do a query with JOIN on two tables, but I am struggling with joining these three tables.
Something like
SELECT
*
FROM
option
WHERE
code = #code
AND optionsSetId IN
(SELECT
os.id
FROM
optionsSet os
JOIN product p ON os.productId = p.Id
WHERE
p.siteId = #siteId)
where #code is your code parameter and #siteId is your siteid parameter
to use inner joins you would have to join all 3 tables together and that would like
SELECT
DISTINCT o.*
FROM
option o
JOIN optionsSet os ON o.optionsSetId = os.Id
JOIN product p ON os.productId = p.Id
WHERE
o.code = #code
AND p.siteId = #site
if you notice that requires a DISTINCT to only get the data from option. It may be simpler and easier to understand but not very efficient.
another option that someone will probably say is way more awesome is using EXISTS
SELECT
o.*
FROM
OPTION o
WHERE
o.code = #code
AND EXISTS(
SELECT
1
FROM
optionsSet os
JOIN product p ON os.productId = p.Id
WHERE
o.optionSetId = os.Id
AND p.siteId = #siteId
)
I used EXISTS exclusively for a few years and the started working on databases with tables that had +100million records and IN was faster than EXISTS in some cases and identical in the others. Plus IN is less code.
SELECT * FROM option
LEFT JOIN product
ON option.code = product.siteId (+)
--(+) is a left outter join. This should include all of the values in option.code and all of the values in product that have the same siteId as values in option.
I'm unsure on how you want OptionSet to relate to the other 2 databases though?
if you want to include the third tables result you can just add another join on that table for the condition you want.

Query with columns from 4 tables in SQL

Can anyone who knows SQL, specifically the flavor used in Microsoft Access 2013, tell me what I'm doing wrong here?
SELECT custid, custname, ordno, itemno, itemname
FROM cust
INNER JOIN order
ON cust.custid = order.custid
INNER JOIN orderitems
ON order.ordno = orderitems.ordno
INNER JOIN inv
ON orderitems.itemno = inv.itemno;
I've already read other, similar questions, and tried the methods they used in their solutions, but I'm getting a "Syntax error in FROM clause.", almost no matter what I try.
* * *
SOLUTION: Thanks for the replies! In addition to adding square brackets around "order" and using TableName.ColumnName syntax in SELECT, I had to use parentheses for my multiple INNER JOINs. Here is the fixed code:
SELECT cust.custid, cust.custname, [order].ordno, orderitems.itemno, inv.itemname
FROM ((cust
INNER JOIN [order]
ON cust.custid = [order].custid)
INNER JOIN orderitems
ON [order].ordno = orderitems.ordno)
INNER JOIN inv
ON orderitems.itemno = inv.itemno;
SELECT cust.custid --<-- Use two part name here
,cust.custname
,[order].ordno
,orderitems.itemno --<-- Only guessing here use the correct table name
,inv.itemname --<-- Only guessing here use the correct table name
FROM cust
INNER JOIN [order]
ON cust.custid = [order].custid --<-- used square brackets [] around ORDER as it is
INNER JOIN orderitems -- a key word.
ON [order].ordno = orderitems.ordno
INNER JOIN inv
ON orderitems.itemno = inv.itemno;
In your Select Statament you need to use Two Part name i.e TableName.ColumnName since these column can exist in more than one Tables in your FROM clause you need to tell sql server that columns in your select coming from which table in your from clause.

Error in query: aggregate function or the GROUP BY clause

Hi all I have a problem with an SQL query: the problem is that if i add GROUP BY the database engine outputs the error:
Column 'dbo.classes.class_name' is invalid in the select list because
it is not contained in either an aggregate function or the GROUP BY clause.
My query is:
string query = "SELECT p.*
FROM dbo.classes AS p INNER JOIN teacher_classes AS a
ON a.class_id = p.class_id
and teach_id = #id
GROUP BY p.class_id";
Is there any help please for that.
Note without group by the query work fine but the result not grouped.
Your query is:
SELECT p.*
FROM dbo.classes AS p INNER JOIN
teacher_classes AS a
ON a.class_id = p.class_id and teach_id = #id
GROUP BY p.class_name;
You are trying to select all the columns from p and yet you're are grouping by class_name. This is not allowed in most databases. What happens if you have two classes, but information is different from them?
One option is to use distinct rather than group by to remove duplicates:
SELECT distinct c.*
FROM dbo.classes c INNER JOIN
teacher_classes tc
ON tc.class_id = c.class_id and tc.teach_id = #id;
Another option is to use something like in to find the matching classes for the teacher:
select c.*
from classes c
where c.class_id in (select tc.class_id from teacher_classes where teach_id = #id)
Notice I also changed your aliases so they have some relationship to the table names. This makes the query much easier to read.

Translate an SQL subquery to a more efficient version

I'm working with a moderately large MSAccess .mdb file that I need to manipulate with SQL. Unfortunately some statements which work in theory seem to cause it to hang, and I've run into a brick wall.
Here is a simplified representation in SQL Fiddle
Three tables: products, product_category, and categories
I need to SELECT categories that ONLY contain items that have the field 'HIDE = 1'
If a category contains products that are hide = 0, it should not be selected.
I can do this relatively easily with subqueries, but the query stalls out. In the past queries that rely on left joins seem to execute efficiently, but I cannot wrap my mind around joins enough to translate this query into that format.
EDIT:
SELECT c.categoryid
FROM product_category AS c
LEFT JOIN
(
SELECT DISTINCT c.categoryid
FROM product_category AS c
LEFT JOIN products AS p
ON c.catalogid = p.catalogid
WHERE p.hide = 0
) y ON y.categoryid = c.categoryid
WHERE y.categoryid IS NULL
Someone posted the above query as an answer but then for some reason deleted it. As far as I can tell it works and works quickly. I consider this question to be answered. If I remember I will self-post the answer once the timer allows me to.
I believe you just need to un-correlate the subquery eg...
SELECT c.categoryid FROM product_category AS c
WHERE c.categoryid NOT IN
(SELECT DISTINCT c1.categoryid FROM product_category AS c1
LEFT JOIN products AS p ON c1.catalogid = p.catalogid
WHERE p.hide = 0)
Note how I have aliased the subquery product_category table as c1 instead of c - This means the subquery will only execute once as opposed to once for every row of the your main query.
SQL Fiddle
Note that there will no doubt be more efficiencies still to be found however I think this will suffice for your purposes.
In fact there is no need for a LEFT JOIN here I don't think ie...
SELECT c.categoryid FROM product_category AS c
WHERE c.categoryid NOT IN
(SELECT DISTINCT c1.categoryid FROM product_category AS c1
INNER JOIN products AS p ON c1.catalogid = p.catalogid
WHERE p.hide = 0)
..This will afford you some extra speed.
If there is only one categoryid per catalogid then you can get rid of the distinct:
Select
c.id, c.categoryname
From
category c
Where
Not Exists (
Select
'x'
From
products p
Inner Join
product_category pc
on pc.catalogid = p.catalogid
Where
pc.categoryid = c.id and
p.hide = 0
)
Edited - the test data in the fiddle seems wrong, I've corrected it. This should work now
http://sqlfiddle.com/#!6/56f5e/1/0