I believe this is an easy one. Just getting started on SQL, so I am finding it a bit tricky. So I am using SQL on SAS, and I want to join two tables but on different columns based on a value of a column. Practical example:
Proc sql;
create table new_table_name as select
a.proposal_code as new_name_proposal_code,
a.1st_client_code as new_name_1st_client_code,
a.2nd_client_code as new_name_2nd_client_code,
a.3rd_client_code as new_name_3rd_client_code,
a.4th_client_code as new_name_4th_client_code,
a.product_type as new_name_product_type,
b.2nd_client_code
from existing_table a
left join existing table b (on b.2nd_client_code=a.2nd_client_code and a.product_type = "clothes") or
left join existing table b (on b.2nd_client_code=a.3rd_client_code and (a.product_type = "cars" or a.product_type = "bikes"));
quit;
So this is the code that I'm using at the moment, and the goal is to join table a and table b using b.2nd client code = a.2nd client code if the product type from table a is = to "clothes", and if the product type from table a is either "cars" or "bikes", join table a and table b using b.2nd client code = a.3rd client code. Basically, look at two different "on's" regarding the specific product type. When joining these two tables, if one row has product type "clothes", I want it to look at the 2nd client code, if it is either "cars" or "bikes", look at the 3rd client code.
Hope I made it clear. The error I am getting at the moment is "expecting an on". Is it a problem of syntax?
Yes. The parentheses before the on is not correct. Your query has other issues as well. I think you want:
create table new_table_name as
select a.proposal_code as new_name_proposal_code,
a.1st_client_code as new_name_1st_client_code,
a.2nd_client_code as new_name_2nd_client_code,
a.3rd_client_code as new_name_3rd_client_code,
a.4th_client_code as new_name_4th_client_code,
a.product_type as new_name_product_type,
coalsesce(bc.2nd_client_code, bcb.2nd_client_code)
from existing_table a left join
existing_table bc
on bc.2nd_client_code = a.2nd_client_code and
a.product_type = 'clothes' left join
existing_table bcb
on bcb.2nd_client_code = a.3rd_client_code and
a.product_type in ('cars', 'bikes');
Notes:
No parentheses before the on clause.
No or left join. or is a boolean operator. left join is an operator on sets (i.e. tables and results sets). The don't mix.
No repeated table aliases.
You want to combine the two code, so you need something like coalesce() in the select.
The SQL delimiter for strings is the single quote, not the double quote.
in is simpler than a string of or conditions.
Sounds like you just want a complex ON criteria and not two joins.
Something like this:
proc sql;
create table new_table_name as
select
a.proposal_code as new_name_proposal_code
,a.client_code1 as new_name_client_code1
,a.client_code2 as new_name_client_code2
,a.client_code3 as new_name_client_code3
,a.client_code4 as new_name_client_code4
,a.product_type as new_name_product_type
,b.client_code2 as new_name_other_client_code2
from tableA a
left join tableB b
on (b.client_code2=a.client_code2 and a.product_type = "clothes")
or (b.client_code2=a.client_code3 and a.product_type in ("cars","bikes"))
;
quit;
For a better answer post example inputs and desired output.
Related
The parameter is an ID that is the primary key for the table1. The other 3 tables contain details for reference against table1. Obviously if I cut out all the joins, I get only data from Table1, with any ID. I would really like to understand what is going on. Thanks.
SELECT
Detail14, Detail15, Detail16, //etc, etc
FROM
Table1
INNER JOIN
dbo.Table2 ON dbo.Table1.FK_AnID = dbo.Table2.PK_AnotherID
INNER JOIN
dbo.tblTable3 ON dbo.Table2.FK_Group = dbo.tblTable3.PK_RowID
LEFT JOIN
dbo.tblTable4 ON dbo.tblTable4.Name = dbo.Table1.Named
WHERE
PK_RefNumber = #AnID
Break this down by doing in steps. Use select * until you have the joins right, then go to the specific fields you want.
So get records for the first table with the where clause (if it is from the first table). Add the second table. If you get records,then that is not the source of the problem and add the third, etc.
Likely you are either joining on the wrong fields or you have an inner join where you need a left join.
I am incredibly new to SQL and am trying to create a view for a pizza store database. The sides ordered table and the sides names table have to be separate but need a view that combines them.
This is the code I have entered,
CREATE VIEW ordered_sides_view
AS
SELECT
ordered_side_id, side.side_id, side_name, number_ordered,
SUM(number_ordered * price) AS 'total_cost'
FROM
ordered_side
FULL JOIN
side ON ordered_side.side_id = side.side_id
GROUP BY
ordered_side_id, side.side_id, side_name, number_ordered;
The problem is that this is the resulting table.
Screenshot of view table:
How do I get the names to match the ordered sides?
You fail to understand what a FULL JOIN and an INNER JOIN operation does.
FULL JOIN returns at least every row from each table (plus any extra values from the ON clause).
INNER JOIN returns only matching row sets based on the ON clause.
OUTER JOIN returns every matching row set PLUS the side of the join that the OUTER JOIN is on (LEFT OUTER JOIN vs RIGHT OUTER JOIN).
In your picture, you can clearly see that there are no rows that match from the tables ordered_side and side...
That is why switching to an INNER JOIN returns zero rows...there are no matches on the COLUMNS YOU CHOSE TO USE.
Why in your SELECT operator do you have this:
SELECT ordered_side_id, side.side_id, side_name, number_ordered,
while your ON clause has this:
side ON ordered_side.side_id = side.side_id
ordered_side_id !=ordered_side.side_id
Investigate your columns and fix your JOIN clause to match the correct columns.
P.S. I like how you structure your queries. Very nice and what an
expert does! It makes reading MUCH, MUCH easier. :)
One suggestion I might add is structure your columns in the SELECT statement in its own row:
SELECT ordered_side_id
, side.side_id
, side_name
, number_ordered
, SUM(number_ordered * price) AS Total_Cost --or written [Total_Cost]/'Total_Cost'
FROM ordered_side
FULL JOIN side ON ordered_side.ordered_side_id = side.side_id
GROUP BY ordered_side_id
, side.side_id
, side_name
, number_ordered;
Struggling with a create table statement which is based on this select into statement below:
#MaxAPDRefundAmount money = 13.00
...
select pkd.*, pd.ProviderReference, per.FirstName, per.Surname, #MaxAPDRefundAmount [MaxAPDRefundAmount],commission.Type [Commission] into #StagedData from CTE_PackageData pkd
inner join J2H.dbo.Package pk on pkd.Reference = pk.Reference
inner join J2H.dbo.Product pd on pk.PackageId = pd.PackageId
inner join J2H.dbo.FlightReservation fr on pd.ProductId = fr.ProductId
and fr.FlightBoundID = 1
inner join J2H.dbo.ProductPerson pp on pd.ProductId = pp.ProductID
and pp.StatusId < 7
inner join J2H.dbo.Flight f on fr.FlightId = f.FlightID
inner join J2H.dbo.Person per on pk.PackageId = per.PackageId
and per.PersonId = pp.PersonId
inner join J2H.dbo.PersonType pt on per.PersonTypeId = pt.PersonTypeID
We are changing a select into to just normal insert and select, so need a create table (we are going to create a temp (hash tag table) and not declaring a variable table. Also there is a pkd.* at the start as well so I am confused in knowing which fields to include in the create table. Do I include all the fields in the select statement into the create statement?
Update:
So virtually I know I need to include the data types below but I can just do:
create table #StagedData
(
pkd.*,
pd.ProviderReference,
per.FirstName,
per.Surname,
#MaxAPDRefundAmount [MaxAPDRefundAmount],
commission
)
"Do I include all the fields in the select statement into the create statement?" Well, that depends, if you need them, than yes, if not than no. It's impossible for us to say whether you need them... If you're running this exact query as insert, than yes.
As for the create statement, you can run the query you have, but replace into #StagedData with something like into TEMP_StagedData. In management studio you can let sql server build the create query for you: right-click the newly created TEMP_StagedData table in the object explorer (remember to refresh), script Table as, CREATE To and select New Query Editor Window.
The documentation of the CREATE TABLE statement is pretty straightforward.
No. Clearly, you cannot use pkd.* in a create table statement.
What you can do is run your old SELECT INTO statement as a straight SELECT (remove the INTO #stagedata) part, and look at the columns that get returned by the SELECT.
Then write a CREATE TABLE statement that includes those columns.
To create a table from a SELECT without inserting data, add a WHERE clause that never returns True.
Like this:
SELECT * INTO #TempTable FROM Table WHERE 1=0
Once the table with the columns for your SELECT, you can add additional columns with ALTER TABLE.
ALTER TABLE #TempTable ALL ExtraColumn INT
Then do your INSERT/SELECT.
I have two tables, Table A and Table B. Each table have 4 fields, the name of the fields are the same for both. Both tables are extracted from other tables, and each record acts as a primary key.
I want to write a query in MS Access 2010 that gets the data unique to Table B and not shared with Table A. I am using the following image as a reference, and it looks like I need to do a Right Join.
Hello. There is something not right with my SQL, I've tested it and I am getting the incorrect result. Below is the closest I've gotten:
SELECT DISTINCT TableB.*
FROM TableB RIGHT JOIN TableA ON (TableB.Field1 = TableA.Field1) AND (TableB.Field2 = TableA.Field2) AND (TableB.Field3 = TableA.Field3) AND (TableB.Field4 = TableA.Field4)
WHERE (((TableA.Field1) Is Null));
I think it would be clearer for you to use not exists:
select tableb.*
from tableb
where not exists (select 1
from tablea
where (TableB.Field1 = TableA.Field1) AND (TableB.Field2 = TableA.Field2) AND (TableB.Field3 = TableA.Field3) AND (TableB.Field4 = TableA.Field4)
);
Your use of RIGHT JOIN is incorrect. As phrased, you want a LEFT JOIN. That is, you want to keep all rows in the first table (the "left" table in the JOIN) regardless of whether or not a match exists in the second table. However, the NOT EXISTS does the same thing and the logic is a bit clearer.
You want to have right join if tablea is in your select statement, but as you have
SELECT DISTINCT TableB.*
you may want to have a left join instead. My suggestion would be changing your code from right to left join.
TableB acts like table A from venn diagrams above.
I am new to SQL and want to compare two tables using inner join and then use the result to compare it with the third table and so on. Also the third table does not share the same column name as compared in the first two.
Below is the SQL statement to compare two tables.
SELECT WORKLOAD_ITEM_ID wid
FROM OUTPUT o
INNER JOIN workload_item wi ON O.WORKLOAD_ITEM_ID = wi.WORKLOAD_ITEM_ID
Now whatever is returned I want to use that and do an inner join with a third table which does not have a column WORKLOAD_ITEM_ID. So the question is how to save and compare the result?
Please Help!
You can follow this to hold records in temp table
INSERT INTO #WORKLOAD_ITEM_TEMP
SELECT WORKLOAD_ITEM_ID wid
FROM OUTPUT o
INNER JOIN workload_item wi ON O.WORKLOAD_ITEM_ID = wi.WORKLOAD_ITEM_ID
Then with your third table made a join with this #WORKLOAD_ITEM_TEMP table.
Now you have to decide on which column need to put inner join. Either add a common column between output result set and third table or use just cross join.
I think you need to reevaluate your Database structure and make efficient tables relationship.