I am using JTable to display the result of a query. Table does not show as XYZ for all columns but it shows XYZ as a header for the fields not existing in database(manipulated fields).
Don't know much of database internals.Please forgive if it's too basic.
rs1 = st1.executeQuery("SELECT product.`id` as `Product ID`,product.`serialnumber` as `Serial Number`, product.`dop` as `Date Of Purchase` FROM product where product.`dop` between '"+from+"' and '"+to+"'");
reportTable.setModel(buildTableModel(rs1));
same query on query browser Output:
Product ID Serial Number Date Of Purchase
1 123244mf43m 08/08/2013
My Output With JDBC is:
id serialnumber dop //table header
1 123244mf43m 08/08/2013
There is a configuration setting described here:
http://dev.mysql.com/doc/refman/5.1/en/connector-j-reference-configuration-properties.html
useOldAliasMetadataBehavior
which, if set to true (the default in 5.0.x) will only return aliases (if any) for ResultSetMetaData.getColumnName() or ResultSetMetaData.getTableName() rather than the original column/table name.
Not sure if this is applicable to you, but could be the cause.
Related
I've got a machine log available in an SQL table. I can do a bit in SQL, but I'm not good enough to process the following:
In the data column there are entries containing "RUNPGM: Recipe name" and "RUNBRKPGM: Recipe name"
What I want is a view containing 4 columns:
TimeStamp RUNPGM
TimeStamp RUNBRKPGM
Recipe Name
Time Difference in seconds
There is a bit of a catch:
Sometimes the machine logs an empty RUNBRKPGM that should be ignored
The RUNBRKPGM is sometimes logged with an error message. This entry should also be ignored.
It's always the RUNBRKPGM entry with just the recipe name that's the actual end of the recipe.
NOTE: I understand this is not a full/complete answer, but with info available in question as of now, I believe it at least helps give a starting point since this is too complicated (and formatted) to put in the comments:
If Recipe is everything in the DATA field except the 'RUNPGM = ' part you can do somethign similar to this:
SELECT
-- will give you a col for TimeStamp for records with RUNPGM
CASE WHEN DATA LIKE 'RUNPGM%' THEN TS ELSE '' END AS RUNPGM_TimeStamp,
-- will give you a col for TimeStamp for records with RUNBRKPGM
CASE WHEN DATA LIKE 'RUNBRKPGM%' THEN TS ELSE '' END AS RUNBRKPGM_TimeStamp,
-- will give you everything after the RUNPGM = (which I think is the recipe you are referring to)
CASE WHEN DATA LIKE 'RUNPGM%' THEN REPLACE(DATA, 'RUNPGM = ', '' AS RUNPGM_Recipe,
-- will give you everything after the RUNBRKPGM = (which I think is the recipe you are referring to)
CASE WHEN DATA LIKE 'RUNBRKPGM:%' THEN REPLACE(DATA, 'RUNBRKPGM = ', '' AS RUNPGM_Recipe
FROM TableName
Im not sure what columns you want to get the Time Difference on though so I dont have that column in here.
Then if you need to do additional logic/formatting on the columns once they are separated you can put the above in a sub select.
As a first swing, I'd try the following:
Create a view that uses string splitting to break the DATA column into a its parts (e.g. RunType and RecipeName)
Create a simple select that outputs the recipe name and tstamp where the runtype is RUNPGM.
Then add an OUTER APPLY:
Essentially, joining onto itself.
SELECT
t1.RecipeName,
t1.TimeStamp AS Start,
t2.TimeStamp AS Stop
--date func to get run time, pseudo DATEDIFF(xx,t1.TimeStamp, t2.TimeStamp) as RunTime
FROM newView t1
OUTER APPLY ( SELECT TOP ( 1 ) *
FROM newView x
WHERE x.RecipeName = t1.RecipeName
AND RunType = 'RUNBRKPGM'
ORDER BY ID DESC ) t2
WHERE t1.RunType = 'RUNPGM';
First of all, I know I should be using the model rather than working on the database directly. That being said, does anyone know exactly how Magento handles non-global product attributes?
I have 2 websites in core_website: Admin (website_id = 0) and Main Website (website_id =1). I also have two stores in core_store: Admin (store_id = 0) and Default Store View (store_id = 0). It seems that whether or not a product (or category?) attribute is global in scope is stored in catalog_eav_attribute.is_global. A value of 0 corresponds to a scope of "Store View," a value of 1 corresponds to "Global," and 2 corresponds to "Website." So far so good.
Now, if I wanted to get the value of a store-specific attribute like "name" (eav_attribute.attribute_id = 71; eav_attribute.backend_type = 'varchar'; catalog_eav_attribute.is_global = 0) for all my products, you would think I would do something like this:
SELECT *
FROM catalog_product_entity_varchar
WHERE attribute_id = 71
AND store_id = 1
But that returns nothing. All of the names are actually in rows with store_id = 0. As far as I can tell the only attributes in the database that are stored with store_id = 1 are 'url_key' and 'url_path'. So how does Magento store these values? And how does Magento retrieve them?
Are all values initially(or also) stored with store_id = 0 as a kind of default, until a different value than that one needs to be stored? When a store-specific value that is different from the admin value needs to be stored, does magento then create a new row with store_id = 1 (or whatever store_id it is)?
If that - or something like that - is the case, then how does Magento retrieve store-specific values? Does it check catalog_eav_attribute.is_global first for the attribute in question? If it is non-global, it could then first query with store_id = 1, and if that returns nothing, then query with the default store_id = 0?
I guess my main question is how does magento actually do it. Secondarily, why does magento do it this way instead of storing values with the actual store_id? Also, if I were to write a query, should I query both store_id = 0 and store_id = 1 and choose the right value based on whether or not the attribute is global and whether or not there is a value present for store_id = 1?
You seem to have it figured out. At least you have a good idea on how things are done.
To summarize and confirm your suspicions:
All the attribute values are stored in catalog_product_entity_* where * can be anyone of theses: decimal, int, varchar, text, datetime depending on the attribute type (backend_type).
There are also other tables that keep the data related to tier pricing and images but let's leave that for now.
Attribute table definition
Each of the tables have the following columns:
value_id - just an increment id for the table
entity_type_id - the entity type id for the product (always the same)
attribute_id - reference to the attribute
store_id - reference to the store view
entity_id - reference to the product
value - actual value
There is a unique constraint on these columns entity_id,attribute_id,store_id. This means that for one product and one attribute you can have only one value for a store view.
Now the part where you are right.
store_id = 0 means that the value stored there is a default value.
If there is no value specified for a specific store view (store_id >= 1) then this value will be used.
If the attribute is set as global then the value for store_id = 0 will be used even if you have values for store_id = 1.
Examples
To get an idea of how the values are retrieved put this code in some file and run it (make sure the flat catalog is disabled - more on that later, and make sure you created an instance of the application first using Mage::app()):
Store view attribute
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToFilter('name', 'some_name');
echo $collection->getSelect();
The code above means that I want to retrieve a list of products with the name some_name.
the sql query associated to the collection looks like this:
SELECT
`e`.*,
IF(at_name.value_id > 0, at_name.value, at_name_default.value) AS `name`
FROM
`catalog_product_entity` AS `e`
INNER JOIN
`catalog_product_entity_varchar` AS `at_name_default`
ON (`at_name_default`.`entity_id` = `e`.`entity_id`) AND
(`at_name_default`.`attribute_id` = '96') AND
`at_name_default`.`store_id` = 0
LEFT JOIN
`catalog_product_entity_varchar` AS `at_name`
ON (`at_name`.`entity_id` = `e`.`entity_id`) AND
(`at_name`.`attribute_id` = '96') AND
(`at_name`.`store_id` = 1)
WHERE
(IF(at_name.value_id > 0, at_name.value, at_name_default.value) = 'some_name')
Ugly huh?
Because the name attribute (id 96 in my case) is a store view scope attribute (is_global = 0) Magento joins twice with the table catalog_product_entity_varchar (the one that holds the name), once for the current store view and once for the detault store view (id = 0). adding a condition:
IF(at_name.value_id > 0, at_name.value, at_name_default.value)
So if there is no value for the store id 1, use the default value.
Global attribtue
Now let's see what happens if we filter by a global attribute.
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToFilter('weight', '1');
echo $collection->getSelect();
The sql printed looks like this:
SELECT
`e`.*,
`at_weight`.`value` AS `weight`
FROM
`catalog_product_entity` AS `e`
INNER JOIN
`catalog_product_entity_decimal` AS `at_weight`
ON (`at_weight`.`entity_id` = `e`.`entity_id`) AND
(`at_weight`.`attribute_id` = '101') AND
(`at_weight`.`store_id` = 0)
WHERE
(at_weight.value = '1')
So one single join with the table catalog_product_entity_decimal for the store id = 0.
Website attribute
If the scope of the attribute is website everything happens just like it does for the store view scope, because Magento creates a line in the attribute values table for each store view in the current website when saving the product.
If you want to try it use the attribute status in the examples above.
Flat Catalog
I promised earlier some explanations about "flat catalog".
For performance reasons Magneto introduced this feature (I don't remember the version).
Basically a cron runs (or you can run it by hand) and transforms the EAV approach for the products and categories into flat tables. One for each store view you have (except store id = 0).
This means one attribute will be transformed into one column in the new table. The new table is called catalog_product_flat_{store_view_id_here}.
This avoids the numerous left/inner joins when wanting the values for some attributes.
but again, for performance reasons, not all the attributes are added as columns in the flat tables (for products only. For categories all of them are added).
Only the attributes marked in the backend with Use in product listing are transformed into columns.
You can turn on/off this feature from System->Configuration->Catalog->Frontend->Use Flat Catalog Product (or Use Flat Catalog Category).
Even if turned on, the flat tables are used only in the frontend. The backend still uses the EAV approach.
Conclusion
My conclusion is that it is almost impossible to write your own queries to retrieve data directly from the DB. You should use the models and collections that magento provides. It saves a lot of mental health.
I hope I made things a little clearer for you.
Using this question's answer. I'm trying to find duplicate records between two tables by the column names matrix_unique_id and Matrix_Unique_ID in each table and then display the full address. The Full address columns are formatted differently from each other in each table so I cannot use that as a comparison. I'm getting an "unknown column fort_property_res.matrix_unique_id" error but everything looks okay?
So two questions:
Will this query find duplicates correctly?
Why the unknown column error?
SQL query:
SELECT matrix_unique_id, full_address
FROM fort_property_res
INNER JOIN (
SELECT Matrix_Unique_ID, FullAddress
FROM sunshinemls_property_res
GROUP BY FullAddress
HAVING count(fort_property_res.matrix_unique_id) > 1
) dup ON fort_property_res.matrix_unique = sunshinemls_property_res.Matrix_Unique_ID
The solution you're trying to copy is a totally different case. You have two tables and (it looks like) a convenient matrix_unique_id to join on, so this is much easier:
SELECT fort.matrix_unique_id, fort.full_address AS fortAddress, sun.FullAddress AS sunAddress
FROM fort_property_res fort, sunshinemls_property_res sun
WHERE fort.matrix_unique_id = sun.Matrix_Unique_ID
I have one table named task_assignment.It has following 6 fields named as:
testId,quesId,evaluatorId,studId and marks
Actually this table is used to store marks for each test including each evaluators marks for each students by question id wise.
I have testId=1, quesId=Q1 and studId=S1 as a input. So, i want to get the following information in the select query.ie,Both evaluators(E1,E2) marks for the given input.
The sql query don't written more than one row for this...I want query output is :20,15 in a single row.
Please guide me to get out of this issue...
I think you won't be able to get your desired output 20, 15, since there is only one record which satisfies your criteria testId = 1, quesId = Q1, studId = S1.
But to answer your question, here's my query:
SELECT GROUP_CONCAT(marks)
FROM task_assignment
WHERE testId = 1
AND quesId = 'Q1'
AND studId = 'S1';
I've tried it in SQL Fiddle.
EDIT 1
If you want to parse the output of the query in your C# code to store them in separate variables, you can use the Split function:
string marks = "20, 15"; //Suppose that this value came from database
int mark1 = Convert.ToInt32(marks.Split(',')[0]);
int mark2 = Convert.ToInt32(marks.Split(',')[1]);
The code is still error-prone depending on the value of the marks variable, just make sure you have validated the value.
This might be unrelated to the question, but still to help you on your task, that's my answer.
First of all I'm rather new to SQL and so even though I believe a similar question was asked in this thread ( SQL Query - Copy Values in Same Table ) I literally can't understand it well enough to utilize the information. For that I apologize.
Now, I have a table that looks something like this:
company id | parameter name | parameter title
P | Parameter One | First Parameter
P | Parameter Two | Second Parameter
P | Parameter Three| Third Parameter
W | Parameter One | NULL
W | Parameter Two | NULL
Except that my table obviously has quite a lot of rows. I already went through filling in all the parameter titles where the company id was 'P' and would like to avoid manually doing the same for those with company id 'W'. My question is what SQL statement (this is in Microsoft SQL Server 2008) can I use to copy the values in the column "parameter title" where the company id is 'P' to the values in the same column where the company id is 'W' and both parameter names match up (W has less parameters than P)?
Using the previously linked thread I was able to come up with the following, but it spits out an error and I know it's not done correctly:
UPDATE COMP_PARAMETER_COPY
SET PARAM_TITLE=(SELECT PARAM_TITLE FROM COMP_PARAMETER_COPY P
WHERE P.COMP_ID = 'P' AND P.PARAM_TITLE=PARAM_TITLE)
WHERE COMP_ID='W'
(I'm playing around with a copy of the table instead of the actual table)
The error I get is "Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated."
Thank you for your help and advice,
-Asaf
You need to ensure that your subquery is only returning one result. Right now that error message is telling you that you're getting more than one record returned.
UPDATE W
SET PARAM_TITLE = (
SELECT PARAM_TITLE FROM COMP_PARAMETER_COPY P
WHERE P.COMP_ID = 'P' AND P.PARAM_NAME = W.PARAM_NAME
)
FROM COMP_PARAMETER_COPY W
WHERE W.COMP_ID = 'W'
Try giving the above SQL a whirl. This could still give you more than one result, but without knowing what your table looks like and what the data constraints are it's hard to give you something guaranteed to work.
Try adding the DISTINCT keyword to your query:
UPDATE COMP_PARAMETER_COPY
SET PARAM_TITLE=(SELECT DISTINCT PARAM_TITLE FROM COMP_PARAMETER_COPY P
WHERE P.COMP_ID = 'P' AND P.PARAM_TITLE=PARAM_TITLE)
WHERE COMP_ID='W'