Pivoting Concept - mysql

Hiii,
I have a Database design as:
Table File (FileID, Name, Details)
Table Attributes (AttID, AttName, AttType)
Table AttValues (FileID, AttID, AttValue)
Till the runtime, it is not known how many Attributes are in a File and of what names.
And I want to display after insertion at Frontend in a manner like like:
FileID, FileName, Details, (Rows of Attribute Table as Column here).
i.e.,
Can anybody provide me a piece of code in Java or in MySQL to achieve this Pivoting Result.
Highly thanks full for your precious time.
Or is there any other better way to store data, So that I can get the desired result easily.

This requires two queries. First select the File:
SELECT * FROM File WHERE (...)
Then, fetch the Attributes:
SELECT *
FROM AttValues
JOIN Attributes ON (Attributes.AttId = AttValues.AttId)
WHERE FileId = $id
The latter query will provide you with one row per Attribute, which you can programmatically pivot for display on your frontend:
foreach(row in result) {
table.AddColumn(Header = row['AttName'], Value = row['AttValue']);
}
Adapt to your local programming environment as needed.
Of course, this only works for a single File or Files with the same attributes. If you want to display multiple files with different Attributes you can instead prefetch all AttNames:
SELECT Attributes.AttId, Attributes.AttName
FROM Attributes
JOIN AttValues ON (Attributes.AttId = AttValues.AttId)
WHERE FileId IN ( $list_of_ids )
Then load the values like this:
SELECT *
FROM AttValues
WHERE FileId IN ( $list_of_ids )
and use a local associative array to map from AttIds to column indexes.
As a final optimisation, you can combine the last two queries into an OUTER JOIN to avoid the third round trip. While this will probably increase the amount of data transferred, it also makes filling the table easier, if your class library supports named columns.

I answered a similar question recently: How to pivot a MySQL entity-attribute-value schema. The answer is MySQL-specific, but I guess that's OK as the question is tagged with mysql.

Related

SqlAlchemy table name reflection using an efficient method

I am using the code below to extract table names on a database at a GET call in a Flask app.:
session = db.session()
qry = session.query(models.BaseTableModel)
results = session.execute(qry)
table_names = []
for row in results:
for column, value in row.items():
#this seems like a bit of a hack
if column == "tables_table_name":
table_names.append(value)
print('{0}: '.format(table_names))
Given that tables in the database may added/deleted regularly, is the code above an efficient and reliable way to get the names of tables in a database?
One obvious optimization is to use row["tables_table_name"] instead of second loop.
Assuming that BaseTableModel is a table, which contains names of all other tables, than you're using the fastest approach to get this data.

Replacing existing View but MySQL says "Table doesn't exist"

I have a table in my MySQL database, compatibility_core_rules, which essentially stores pairs of ids which represent compatibility between parts which have fields with those corresponding ids. Now, my aim is to get all possible compatibility pairs by following the transitivity of the pairs (e.g. so if the table has (1,2) and (2,4), then add the pair (1,4)). So, mathematically speaking, I'm trying to find the transitive closure of the compatibility_core_rules table.
E.g. if compatibility_core_rules contains (1,2), (2,4) and (4,9), then initially we can see that (1,2) and (2,4) gives a new pair (1,4). I then iterate over the updated pairs and find that (4,9) with the newly added (1,4) gives me (1,9). At this point, iterating again would add no more pairs.
So my approach is to create a view with the initial pairs from compatibility_core_rules, like so:
CREATE VIEW compatibility_core_rules_closure
AS
SELECT part_type_field_values_id_a,
part_type_field_values_id_b,
custom_builder_id
FROM compatibility_core_rules;
Then, in order to iteratively discover all pairs, I need to keep replacing that view with an updated version of itself that has additional pairs each time. However, I found MySQL doesn't like me referencing the view in its own definition, so I make a temporary view (with or replace, since this will be inside a loop):
CREATE OR REPLACE VIEW compatibility_core_rules_closure_temp
AS
SELECT part_type_field_values_id_a,
part_type_field_values_id_b,
custom_builder_id
FROM compatibility_core_rules_closure;
No problems here. I then reference this temporary view in the following CREATE OR REPLACE VIEW statement to update the compatibility_core_rules_closure view with one iteration's worth of additional pairs:
CREATE OR REPLACE VIEW compatibility_core_rules_closure
AS
SELECT
CASE WHEN ccr1.part_type_field_values_id_a = ccr2.part_type_field_values_id_a THEN ccr1.part_type_field_values_id_b
WHEN ccr1.part_type_field_values_id_a = ccr2.part_type_field_values_id_b THEN ccr1.part_type_field_values_id_b
END ccrA,
CASE WHEN ccr1.part_type_field_values_id_a = ccr2.part_type_field_values_id_a THEN ccr2.part_type_field_values_id_b
WHEN ccr1.part_type_field_values_id_a = ccr2.part_type_field_values_id_b THEN ccr2.part_type_field_values_id_a
END ccrB,
ccr1.custom_builder_id custom_builder_id
FROM compatibility_core_rules_closure_temp ccr1
INNER JOIN compatibility_core_rules_closure_temp ccr2
ON (
ccr1.part_type_field_values_id_a = ccr2.part_type_field_values_id_a OR
ccr1.part_type_field_values_id_a = ccr2.part_type_field_values_id_b
)
GROUP BY ccrA,
ccrB
HAVING -- ccrA and ccrB are in fact not the same
ccrA != ccrB
-- ccrA and ccrB do not belong to the same part type
AND (
SELECT ptf.part_type_id
FROM part_type_field_values ptfv
INNER JOIN part_type_fields ptf
ON ptfv.part_type_field_id = ptf.id
WHERE ptfv.id = ccrA
LIMIT 1
) !=
(
SELECT ptf.part_type_id
FROM part_type_field_values ptfv
INNER JOIN part_type_fields ptf
ON ptfv.part_type_field_id = ptf.id
WHERE ptfv.id = ccrB
LIMIT 1
)
Now this is where things go wrong. I get the following error:
#1146 - Table 'db509574872.compatibility_core_rules_closure' doesn't exist
I'm very confused by this error message. I literally just created the view/table only two statements ago. I'm sure the SELECT query itself is correct since if I try it by itself and it runs fine. If I change the first line to use compatibility_core_rules_closure2 instead of compatibility_core_rules_closure then it runs fine (however, that's not much use since I need to be re-updating the same view again and again). I've looked into the SQL SECURITY clauses but have not had any success. Also been researching online but not getting anywhere.
Does anyone have any ideas what is happening and how to solve it?
MySQL doesn't support sub-queries in views.
You'll have to separate them... ie. using another view containing the sub-query inside you main view.
Running the create statement for that view will render an error, not creating it, hence the doesn't exist error you're getting when querying it.

MySQL WHERE clause not working after CSV import

I have a problem with a MySQL WHERE clause. I think I know what the problem is, just not how to fix it.
I have a database with student timetable information and I'm matching this against a table with student information. The student information has been imported into the database from a CSV (utf-8) file, the other information was just inserted into the database with "normal" INSERT queries.
The WHERE clause is simple and looks like this:
WHERE gpu_timetable.cls_name =
(SELECT cls_name FROM gpu_students WHERE std_number = 123441 LIMIT 1)
Its matching the cls_name (class name) from the timetable against the class name from the students table. Like I said the data is from different sources but looks to be the same. For example when I remove the SELECT query and use this string ('LV6A') the code works.
The collation on both of the fields is *utf8_general_ci*, I also tried TRIM() but no success, the same for replacing the operator = with LIKE.
Did I do something wrong when importing the student information or is there another function similar to TRIM() that can fix this weird problem?
Your simplified query must be:
SELECT * FROM gpu_timetable INNER JOIN gpu_students ON gpu_timetable.cls_name = gpu_students.cls_name WHERE gpu_students.std_number = 123441
Your should always have tablename.fieldname while using JOIN queries.

MySQL merge data from related tables and export as .csv

I don't know MySQL very well so I need a bit of help with this task.. I hope it's ok to ask.
I have a table that i need to export which i did using the following code:
SELECT *
FROM `members`
WHERE `active` =1
AND `level` = 'full'
LIMIT 0 , 30000
This works perfect and gives me most of what I need including a user ID in the collumn called id but I also need to grab the related image for each member and add it to my exported .csv.
The images (filename) are stored in a different table called images but this only contains galleryid, filename and defaultimg (note I am only interested in data where defaultimg = 1)
The issue here is there is NO reference to the member (id) in this table.
For that I have to reference a different table called: imagelinks which contains 2 columns:
1) id which relates to my galleryid from the images table.
and
2) memberid which relates to the user ID id from the members table.
What a disaster of a setup I know.
So.. what I need to do and can't for the life of me work out is export a .csv with ALL the user data from the members table (as stated in my code above) with the addition of the filename data from the images table that coresponds to the referenced user (where defaultimg = 1).
Lastly, I also need to prepend a URL to the front of the filename data.
eg: The table has my-image.jpg but in the exported .csv I need it to be http://www.domain.com/images/my-image.jpg
I'm trying to do all of this in PhpMyAdmin.
Any help with this will be very much appreciated.
Thanks
My syntax might be a bit off but this should be close...
SELECT members.*, CONCAT('http://www.domain.com/images/', images.filename) AS thefilename FROM members INNER JOIN imagelinks ON members.id=imagelinks.memberid INNER JOIN images ON images.galleryid=imagelinks.id WHERE members.active=1 AND members.level='full' AND images.defaultimg=1

Copying duplicates into new table - Old MySQL version complicates

Due to an older version of MySQL I'm having to use some pretty outdated methods to get things done.
At the moment I am trying to copy similar rows to another table based on a few distinct columns. The table holddups will be taking data from assets where the SKU and Description match those of one in holdkey. The command I'm running is:
INSERT INTO holddups
SELECT *
FROM assets, holdkey
WHERE assets.SKU = holdkey.SKU
AND assets.Description = holdkey.Description
And the error I'm getting is:
#1136 - Column count doesn't match value count at row 1
I hope this is enough to sort this all out, but if not feel free to ask more.
Selecting just * will take all columns from assets and holdkey and try to put it in holdups. But holdups does not have that much columns. Using assets.*will only take all columns of assets and that is what you want, right?
INSERT INTO holddups
SELECT assets.*
FROM assets, holdkey
WHERE assets.SKU = holdkey.SKU
AND assets.Description = holdkey.Description