Join only subset of columns with sqlalchemy core - sqlalchemy

Is there a clean way to join two tables but only select a subset of the joined table's columns?
e.g.
join_query = table_a.join(table_b, columns=[table_b.c.column_a, table_b.c.column_b])
I'm trying to avoid using select since I would have to list dozens of needed columns from table_a, but I want only a couple columns from column b.

Stumbled upon the way to do it, select can take either specific columns or full table references as args, so the answer would be
join_query = table_a.join(table_b).select(table_a, table_b.c.column_a, table_b.column_b)

Related

How to avoid duplicate columns when doing left join?

I have two tables. Each has number of columns. But both has two columns in common.(ie: SiteCode,companyId)
I try to do left join for both common columns to create a view.
CREATE VIEW [dbo].[vwAlarmActionSummaryYFUserSite]
AS
SELECT *
FROM [dbo].[vwAlarmActionSummary] alarmaction
LEFT JOIN [dbo].[vwYfUserToSiteMappings] usersite on alarmaction.SiteCode = usersite.SiteCode
and alarmaction.CompanyId = usersite.CompanyId
But Im getting
Column names in each view or function must be unique. Column name 'SiteCode'on 'vwAlarmActionSummaryYFUserSite' is specified more than once.
How can I avoid this?
My requirement is get all columns from those two tables based on the above two conditions
It is very bad practice to use * in definitions view generally. There is no way to specifically exclude a column from one of the joined tables. However, you can use * (all columns) for one table, while providing explicit column names for the other, as below:
CREATE VIEW [dbo].[vwAlarmActionSummaryYFUserSite]
AS
SELECT
alarmaction.[column name],
...
usersite.*
FROM [dbo].[vwAlarmActionSummary] alarmaction
LEFT JOIN [dbo].[vwYfUserToSiteMappings] usersite on
alarmaction.SiteCode = usersite.SiteCode
and alarmaction.CompanyId = usersite.CompanyId
Best practice is still to explicitly list all columns from both tables, and include 'SiteCode' only once.
Don't select *. Pick your column names.

SQL Query Help on 3 Tables with a Many to Many relationship

I had an issue joining multiple tables to retrieve the data I needed. In order to accomplish the proper results I had to first create a view (shown below) called: vwinvgrossrev :
SELECT dbo.inv_item.inv_num, dbo.inv_item.co_line,
dbo.inv_hdr.co_num, dbo.inv_hdr.inv_date, dbo.inv_item.qty_invoiced,
dbo.inv_item.price
FROM dbo.inv_item INNER JOIN
dbo.inv_hdr ON dbo.inv_item.inv_num = dbo.inv_hdr.inv_num
and then I had to join the view on my final table in order to create a proper summation of the values that I wanted
select sum(vwinvgrossrev.qty_invoiced*vwinvgrossrev.price)
from vwinvgrossrev,coitem
WHERE vwinvgrossrev.co_num=coitem.co_num
AND coitem.Uf_Erne='Y'
AND vwinvgrossrev.co_line=coitem.co_line
AND DATEPART(mm,vwinvgrossrev.inv_date) = DATEPART(mm,Getdate())
AND YEAR(vwinvgrossrev.inv_date) = YEAR(Getdate())
My question is this. Is there anyway to do this in a single query. The problem is all 3 tables have a many to many relationship with one another and always returns the wrong value when joining all 3 tables.
If your current query (using the view) gives you what you are looking for then I believe that this query will give you the same thing in a single query:
SELECT sum(inv_item.qty_invoiced*inv_item.price)
FROM inv_item
JOIN inv_hdr ON dbo.inv_item.inv_num = dbo.inv_hdr.inv_num
JOIN coitem ON (inv_hdr.co_num=coitem.co_num
AND inv_item.co_line=coitem.co_line)
WHERE coitem.Uf_Erne='Y'
AND vwinvgrossrev.co_line=coitem.co_line
AND DATEPART(mm,inv_hdr.inv_date) = DATEPART(mm,Getdate())
AND YEAR(inv_hdr.inv_date) = YEAR(Getdate())
However, I'll be surprised if that is what you are looking for.
I am assuming that you don't actually have a many-to-many between all 3. I am assuming that inv_hdr has a unique inv_num and inv_item has many of those. Similarly I am assuming that co_num is unique within inv_hdr but has multiple occurrences within coitem. These are not many-to-many but rather 1-to-many relationships. Since SELECT multiplies rows I think you are going to be summing way more than you want.
Why do you want to include coitem at all if you are just interested in inv_item.qty_invoiced and inv_item.price? Is it just to limit on the Uf_Erne column? Is coitem always going to have either 1 or 0 records for that co_num and co_line with Uf_Erne='Y'?
In sum, I've reproduced your query in a single query without a view, but I think you may need to think through whether this is really what you want.
You need to refine your database schema to normalise out the many-to-many relationships. That is a given and is standard practice regardless of your current problem. The fact that it will simplify your current problem is the reason why. There are many tutorials/blog/etc out there to show you how to do this with join tables so I am not going into it here.

Joining 5 tables - 1 master plus 4 with multiple rows to the master but master data is duplicated

I am working in mysql with queries, but I am new to this. I am joining 5 tables where each table has an identifier and one table is the master. Each related table may have more than one associated record to the master table. I am attempting to join these tables but I can't seem to get rid of the duplicated data.
I want all of the related records to be displayed, but I don't want the data in the master table to display for all results in the related tables. I have tried so many different methods but nothing has worked. Currently I have 4 queries that work for the separate tables, but I have not successfully joined them to have the results display the multiple records in the related table but just one record from the master table.
Here are my individual queries that work:
SELECT
GovernmaxAdditionsExtract.AdditionDescr,
GovernmaxAdditionsExtract.BaseArea,
GovernmaxAdditionsExtract.Value
FROM
GovernmaxExtract
INNER JOIN GovernmaxAdditionsExtract
ON GovernmaxExtract.mpropertyNumber = GovernmaxAdditionsExtract.PropertyNumber
WHERE (((GovernmaxExtract.mpropertyNumber)="xxx-xxx-xx-xxx"));
SELECT
GovernmaxExtract.mpropertyNumber,
GovernmaxDwellingExtract.CardNumber,
GovernmaxDwellingExtract.MainBuildingType,
GovernmaxDwellingExtract.BaseArea
FROM
GovernmaxExtract INNER JOIN
GovernmaxDwellingExtract ON GovernmaxExtract.mpropertyNumber = GovernmaxDwellingExtract.PropertyNumber
WHERE (((GovernmaxExtract.mpropertyNumber)="xxx-xxx-xx-xxx"));
Using these sub queries, I tried to put together 2 of the tables, but now I am getting all records back and it is not reading my input parameter:
SELECT GE.mpropertynumber
FROM
GovernmaxExtract AS GE,
(SELECT
GovernmaxAdditionsExtract.AdditionDescr,
GovernmaxAdditionsExtract.BaseArea,
GovernmaxAdditionsExtract.Value
FROM GovernmaxExtract INNER JOIN
GovernmaxAdditionsExtract ON
governmaxextract.mpropertyNumber = GovernmaxAdditionsExtract.PropertyNumber) AS AE
WHERE GE.mpropertynumber = 'xxx-xxx-xx-xxx'
I tried nested queries, lots of different joins, and I am just not able to wrap my head around this. I am pretty sure I want to do a nested query since I want the main data from the Governmax table to display once with the main data and all records with all info for the associated tables. Maybe I am going about it all wrong.
Our original code was:
SELECT
ge.*,
gde.*,
gfe.*,
gae.*,
goie.*
FROM governmaxextract AS ge
LEFT JOIN governmaxdwellingextract AS gde
ON ge.mpropertyNumber = gde.PropertyNumber
LEFT JOIN governmaxfeaturesextract AS gfe
ON gde.PropertyNumber = gfe.PropertyNumber
LEFT JOIN governmaxadditionsextract AS gae
ON gde.PropertyNumber = gae.PropertyNumber
RIGHT JOIN governmaxotherimprovementsextract AS goie
ON gde.PropertyNumber = goie.PropertyNumber
WHERE ge.mpropertyNumber = '$codeword'
ORDER BY goie.CardNumber
But this gives multiple rows from the master table for each record in the associated tables. I thought about concatenate, but I need the data from the associated tables to be displayed individually. Not sure what to try next. Any help is much appreciated.
Sorry, and there is no way to do that like you want. JOIN's can't do that.
I suggest to keep solution with separate queries.
Btw - You could play with UNION operator,
http://en.wikipedia.org/wiki/Union_(SQL)#UNION_operator
P.s.
You could extract main data separately, then extract data from related tables at once using UNION. With UNIOM it will give one result row per each row in related table.
In order to join an two of the Detail tables together without generating duplicate rows, you will have to perform the following operation on each one:
Group on the foreign key to the Master table, and aggregate all other columns being projected onto the join.
Numeric columns are commonly aggregated with SUM(), COUNT(), MAX(), and MIN(). MAX() and MIN() are also applicable to character data. A PIVOT operation is also sometimes useful as an aggregation operator for this type of circumstance.
Once you have two of the Detail tables grouped and aggregated in this way, they will join without duplicates. Additional Detail tables can be added to the join by first grouping and aggregating them also, in the same fashion.

Merging two tables

I have two tables with the following descriptions:
record(record_id,min_index,max_index)
points(point_id,point_name,val1,val2,rank), point_id being on auto-increment
The min_index,max_index from record table points to the point_ids in the point table.
i.e. for a particular record, the respective points are >=min_index and <=max_index.
I need to merge these two tables such that, the final table resembles something like this
points(point_id,record_id,point_name,val1,val2,rank)
I know this is against the normalisation criteria, but this seems to work very well with the problem i have. I'm not sure on how to go about merging these two tables.
Just join the tables using MySQL's BETWEEN ... AND ... operator to specify your join criterion:
SELECT points.point_id,
record.record_id,
points.point_name,
points.val1,
points.val2,
points.rank
FROM points JOIN record ON
points.point_id BETWEEN record.min_index AND record.max_index
SELECT a.point_id,
b.record_id,
a.point_name,
a.val1,
a.val2,
a.rank
from points a , record b
where ((point_id>=min_index)and (point_id<=max_index))

MySQL JOIN based on dynamic LIKE statement between multiple tables

I have a table called faq. This table consists from fields faq_id,faq_subject.
I have another table called article which consists of article_id,ticket_id,a_body and which stores articles in a specific ticket. Naturally there is also a table "ticket" with fields ticket_id,ticket_number.
I want to retrieve a result table in format:
ticket_number,faq_id,faq_subject.
In order to do this I need to search for faq_id in the article.a_body field using %LIKE% statement.
My question is, how can I do this dynamically such that I return with SQL one result table, which is in format ticket_number,faq_id,faq_subject.
I tried multiple configurations of UNION ALL, LEFT JOIN, LEFT OUTER JOIN statements, but they all return either too many rows, or have different problems.
Is this even possible with MySQL, and is it possible to write an SQL statement which includes #variables and can take care of this?
First off, that kind of a design is problematic. You have certain data embedded within another column, which is going to cause logic as well as performance problems (since you can't index the a_body in such a way that it will help the JOIN). If this is a one-time thing then that's one issue, but otherwise you're going to have problems with this design.
Second, consider this example: You're searching for faq_id #123. You have an article that includes faq_id 4123. You're going to end up with a false match there. You can embed the faq_id values in the text with some sort of mark-up (for example, [faq_id:123]), but at that point you might as well be saving them off in another table as well.
The following query should work (I think that MySQL supports CAST, if not then you might need to adjust that).
SELECT
T.ticket_number,
F.faq_id,
F.faq_subject
FROM
Articles A
INNER JOIN FAQs F ON
A.a_body LIKE CONCAT('%', F.faq_id, '%')
INNER JOIN Tickets T ON
T.ticket_id = A.ticket_id
EDIT: Corrected to use CONCAT
SELECT DISTINCT t.ticket_number, f.faq_id, f.faq_subject
FROM faq.f
INNER JOIN article a ON (a.a_body RLIKE CONCAT('faq_id: ',faq_id))
INNER JOIN ticket t ON (t.ticket_id = a.ticket_id)
WHERE somecriteria