I need your help in one SQL Query for converting the example table given below. Where I need Facilities as columns.
Seasonid
Product
Facility
Price
Product Type
1
Socks
Montreal
24
Wool
2
Slippers
Mexico
50
Poly
3
Slippers
Montreal
27
Rubber
4
Socks
Mexico
24
Cotton
5
Socks
Montreal
26
Cotton
Below table is how I'm expecting it to look like
seasonid
Product
Montreal
Mexico
Product Type
1
Socks
24
0
Wool
2
Slippers
0
50
Poly
3
Slippers
27
0
Rubber
4
Socks
0
24
Cotton
5
Socks
26
0
Cotton
In the expected result table even though 5th row data can be accommodated in 4th row itself like
seasonid
Product
Montreal
Mexico
Product Type
4
Socks
26
24
Cotton
my requirement requires it in a different row.
I found some pivot examples online, but they only show averaging or summing up the values and won't add the rows to already existing columns and display them all. I couldn't find a relevant post for this question. Please let me know if there is any relevant post.
Is it possible with Sql in the first place? If yes, then how?
I think you're mistaken about the pivot part because there's no pivot happening here. This can be achieved with IF() or CASE expression functions added to a very basic MySQL syntax. So, this:
SELECT * FROM mytable;
Will return you all columns and rows. Then this:
SELECT Seasonid, Product, Facility, Price, ProductType
FROM mytable;
is basically the same as the query before-that will return all columns and rows. Only difference is here we're explicitly defining all the column names from the table. So, from here you only need to modify the Facility and Price part with conditional IF() or CASE() and define it twice in the SELECT section, like this:
SELECT seasonid,
Product,
CASE WHEN Facility='Montreal' THEN Price ELSE 0 END AS 'Montreal',
CASE WHEN Facility='Mexico' THEN Price ELSE 0 END AS 'Mexico',
ProductType
FROM mytable;
Or
SELECT seasonid,
Product,
IF(Facility='Montreal',Price,0) AS 'Montreal',
IF(Facility='Mexico',Price,0) AS 'Mexico',
ProductType
FROM mytable;
In which both queries are able to get your desired result.
Demo fiddle
Related
I have a table like
Col 1.
Col 2
Col 3
Apple
2021
Pears
2021
Apple
2020
2
Pears
2020
207
Banana
2017
272
I want to fill Col 3 where col 1 have same values
Col 1.
Col 2
Col 3
Apple
2021
2
Pears
2021
207
Apple
2020
2
Pears
2020
207
Banana
2017
272
I tried self join but that's not working.. Any way I could get this result.
This is bad practice, assuming you're working with a SQL database. It is unnecessarily complex and generally a waste of storage space. Not to mention, if you want to change something, you'd have to do it multiple times (like you're currently doing, right now.)
Why don't you instead try normalization?
This is a resource for you to start - https://www.w3schools.in/dbms/database-normalization
For example -
Build 2 separate tables for the two entities; in this case, dates and fruits with corresponding Primary Keys (Date_Id and Fruit_Id respectively.)
and simply join them with a Junction Table, referencing the previously mentioned above Primary Keys as Foreign Keys
If you want to see a full table, ̷n̷o̷t̷ ̷s̷o̷ simply use the JOIN Keyword.
for reference - https://www.w3schools.com/sql/sql_join.asp
and
https://learnsql.com/blog/how-to-join-3-tables-or-more-in-sql/
example -
SELECT
Fruits.Fruit_Name,
Fruits.Fruit_Amount,
Dates.Date_Value
FROM Fruits
JOIN Junction_Table
ON Fruits.Fruit_Id = Junction_Table.Fruit_Id
JOIN Dates
ON Dates.Date_Id = Junction_Table.Date_Id;
Would produce
I am trying to find products that were bought outside of working hours (9-5). I'm trying to find all of the times that products were bought outside of the 9-5 working hours. However, yellow shirts can be purchased from 7 AM to 5 PM. I'm not sure how to do 2 Where Clauses for that.
There are 100 products. Here is an example:
Product Time_Purchased
Toothbrush 8:00 AM
Yellow Shirt 7:00 AM
Orange Sweatshirt 9:00 AM
Tablet Decoration 10:00 AM
Yellow Shirt 6:00 AM
With this example, the output for Yellow Shirts should not include the 8 AM Time, but it should include the 6 AM.
This is the code I tried running:
PROC SQL
Select * FROM Example
Where (Time_Purchased NOT BETWEEN 32400 AND 61200)
AND Product = 'Yellow Shirt' AND Time_Purchased <25200
quit;
When I run this code, I only get Yellow Shirts purchased before 7:30 and it ignores all of the other products. I'm not sure how to edit the code to show all of the products other than yellow shirts that were purchased outside of 9-5 and the yellow shirts that were purchased outside of 7:30-5 using Where statements.
You can use the OR operator to seperate the 2 conditions in your query. What the OR operator does is return a result if any of the WHERE conditions is true. In your case this would be either 1) when the product is not a yellow shirt and is sold between 9-5 or 2) when the product is a yellow shirt and is sold between 7-5. The query would be similar to the one below:
PROC SQL
SELECT * FROM Example
WHERE Time_Purchased BETWEEN 25200 AND 61200 AND Product = 'Yellow Shirt'
OR Time_Purchased BETWEEN 32400 AND 61200 AND Product != 'Yellow Shirt'
QUIT;
This should work for you.
Sounds simple but I couldn't find the solution for it.
I have a table with 3 columns. Account, Amount, Date.
I want to get all entries except the ones of one specific account with negative amount. But I still want to get the entries of this account if amount value is positive.
So with this query I'm also not getting the entries from account1 with a positive amount.
select * from table where (account!='account1' AND amount<='0') AND date='2020-05-01'
You can do this using WHERE NOT in your statement.
Example schema:
Account Amount Date
=====================================
1 Ben 200 2020-10-10
2 Frank 200 2020-10-10
3 Ben -300 2020-10-12
4 Ben 10 2020-10-16
5 Mary 2000 2020-10-16
6 Frank -200 2020-10-18
7 Ben -10 2020-10-18
8 Ben 0 2020-10-20
Now if you build your query like this
SELECT * FROM t1 WHERE NOT (account='Ben' AND amount<0);
you should get what you want (all records except the 3rd and 7th).
Edit: if you really only want to exclude records with negative amounts, you need to do < rather than <= as you did in your example above. Depends on whether you want row 8 to be included in the result or not.
I am wondering if any of you would be able to help me. I am trying to loop through table 1 (which has duplicate values of the plant codes) and based on the unique plant codes, create a new record for the two other tables. For each unique Plant code I want to create a new row in the other two tables and regarding the non unique PtypeID I link any one of the PTypeID's for all inserts it doesnt matter which I choose and for the rest of the fields like name etc. I would like to set those myself, I am just stuck on the logic of how to insert based on looping through a certain table and adding to another. So here is the data:
Table 1
PlantCode PlantID PTypeID
MEX 1 10
USA 2 11
USA 2 12
AUS 3 13
CHL 4 14
Table 2
PTypeID PtypeName PRID
123 Supplier 1
23 General 2
45 Customer 3
90 Broker 4
90 Broker 5
Table 3
PCreatedDate PRID PRName
2005-03-21 14:44:27.157 1 Classification
2005-03-29 00:00:00.000 2 Follow Up
2005-04-13 09:27:17.720 3 Step 1
2005-04-13 10:31:37.680 4 Step 2
2005-04-13 10:32:17.663 5 General Process
Any help at all would be greatly appreciated
I'm unclear on what relationship there is between Table 1 and either of the other two, so this is going to be a bit general.
First, there are two options and both require a select statement to get the unique values of PlantCode out of table1, along with one of the PTypeId's associated with it, so let's do that:
select PlantCode, min(PTypeId)
from table1
group by PlantCode;
This gets the lowest valued PTypeId associated with the PlantCode. You could use max(PTypeId) instead which gets the highest value if you wanted: for 'USA' min will give you 11 and max will give you 12.
Having selected that data you can either write some code (C#, C++, java, whatever) to read through the results row by row and insert new data into table2 and table3. I'm not going to show that, but I'll show how the do it using pure SQL.
insert into table2 (PTypeId, PTypeName, PRID)
select PTypeId, 'YourChoiceOfName', 24 -- set PRID to 24 for all
from
(
select PlantCode, min(PTypeId) as PTypeId
from table1
group by PlantCode
) x;
and follow that with a similar insert.... select... for table3.
Hope that helps.
id user_id apt_id name value datetime
1 1 1 bp 109 ....
2 1 1 sugar 180 ....
3 2 2 bp 170 ....
I am trying to create the table in this approach because, the patient column is not the standard one, sometimes patient will be store the bp and sugar, sometime only bp.
Am i right in creating the design. If right, how to get the records of single patient.
Thanks,
If am not wrong, userid is your patientid in your scenario, in that case, use the below query to get the single patient record,
select * from Patienttable where user_id = '1'
Here you will get the single patient record. i.e., for user_id = 1
Output:
id user_id apt_id name value datetime
1 1 1 bp 109 ....
2 1 1 sugar 180 ....
Note: You can change as you want instead of 1
Others may disagree, but I wouldn't do it this way, unless you had several changing symptoms that you collect at different appointments. If it's a small collection (some of which are not collected), I would just add them as columns to the appointment table, and leave the sugar column as NULL when it's not collected.
user_id apt_id bp sugar datetime
1 1 109 180 ....
2 1 170 ....
The model you're proposing is a variant of Entity-Attribute-Value design, which has some strengths and some weaknesses. Aaron Bertrand had a good writeup of when an EAV design is useful, and what the costs are for that design. Based on the scenario you described, I don't think it's the best fit.