Whats wrong with these SQL statements? - php

Problem 1: Using the SQL CREATE TABLE statement, create a table, MOVSTARDIR, with attributes for the movie number, star number, and director number and the 4 acting awards. The primary key is the movie number, star number and director number (all 3), with referential integrity enforced. The director number is the director for that movie, and the star must have appeared in that movie.
Load MOVSTARDIR (from existing tables) using INSERt INTO.
My answer:
CREATE TABLE MOVSTARDIR
(MVNUM SHORT NOT NULL, STARNUM SHORT NOT NULL, DIRNUM SHORT NOT NULL, BESTF TEXT, BESTM TEXT, SUPM TEXT, SUPF TEXT)
ALTER TABLE MOVSTARDIR
ADD PRIMARY KEY (MVNUM,STARNUM,DIRNUM)
INSERT INTO MOVSTARDIR
SELECT MOVIE.MVNUM,STAR.STARNUM,DIRECTOR.DIRNUM... BESTF,BESTM,SUPM,SUPF
FROM MOVSTAR, DIRECTOR, MOVIE
WHERE MOVSTAR.MVNUM=MOVIE.MVNUM
AND MOVIE.DIRNUM=DIRECTOR.DIRNUM`
*Its giving me an error saying something is wrong with "create table" statement and it highlights the word "alter" in the SQL statement. Also how do i add referential integrity?*
Problem 2:List the directors in MOVSTARDIR with the total awards won from the 4 award categories included in the table. List the director name (not number), and the count in each of the 4 categories and the sum for all 4 categories. Group the report by the director name (i.e. one line per director, each director appears once), and order it by the sum (descending). Only show lines where the sum is more than 3.
SELECT DISTINCT DIRNAME, COUNT(BESTF) AS BESTFE, COUNT(BESTM) AS BESTML,
COUNT(SUPM) AS SUPML, COUNT(SUPF) AS SUPFE,
(COUNT(BESTM) COUNT(BESTF) COUNT(SUPM) COUNT(SUPF)) AS TOTAL
FROM MOVSTARDIR, DIRECTOR
WHERE MOVSTARDIR.DIRNUM=DIRECTOR.DIRNUM
AND ((BESTM IS NOT NULL) OR (BESTF IS NOT NULL) OR (SUPM IS NOT NULL)
OR (SUPF IS NOT NULL))
GROUP BY DIRNAME
HAVING (COUNT(BESTM) COUNT(BESTF) COUNT(SUPM) COUNT(SUPF)) 3
ORDER BY (COUNT(BESTM) COUNT(BESTF) COUNT(SUPM) COUNT(SUPF))DESC`
*Problem with this is it list all records not just wins*
if the database is needed i can send the data base through email.

For Problem 1:
If you are using mysql, the query for create should be as follows
CREATE TABLE `MOVSTARDIR` (
`MVNUM` SMALLINT NOT NULL ,
`STARNUM` SMALLINT NOT NULL ,
`DIRNUM` SMALLINT NOT NULL ,
`BESTF` TEXT NOT NULL ,
`BESTM` TEXT NOT NULL ,
`SUPM` TEXT NOT NULL ,
`SUPF` TEXT NOT NULL
);

You're missing the semicolon after each of the statements, causing Access to treat the entire text as one statement.

Your tags show MySQL, SQL Server and SQL. The syntax of the SQL can vary according to the RDBMS.
Assuming you are using MySQL, these are the issues with your query.
a. Data type - There is no SHORT in MySQL. You can use SMALLINT
b. You need to add semi colons after each sql statement
Even if you are using any other RDBMS, you need to refer the corresponding SQL manual and verify that you specify the exact data types.

Access doesn't allow to run a batch of queries, only one by one.
So, run first CREATE TABLE, then ALTER and so on.

Related

Store data as varchar, or as tinyint and use switch

Probably a very simple question, but I'm not sure how to test it myself..
Imagine I have a mysql table with let's say, 30000 rows.
Each row has a column car_brand.
In my phpform I have a select with by example, the following car brands: Mercedes, Audi, Chevrolet, Volkswagen, Opel.
What is the fastest (less memory using) way to show the car brand to the user?
Use tinyint and say 0 = Mercedes, 1 = Audi, 2 = Chevrolet... And use a CASE in the SELECT statement or use a php switch() before showing it in a HTML table OR is it better to save the data as a varchar?
Hope someone have a clear answer ;)
The correct way is to use a separate reference table for the brands:
create table CarBrands (
CarBrandId int not null primary key auto_increment,
BrandName varchar(255) not null
);
Then refer to the car brand in other tables using CarBrandId and use a join to get the brand name. This is the right way to handle a reference table.
If you are really opposed to a reference table, then you can use enum.

mySQL query to get only display

I wanted to ask one question as my query skills are not that great and I have been learning mySQL for the last week. This attachment I have shows what happens when I run the following query:
SELECT * FROM clothing, sizing WHERE id = "101";
You might notice that it produces the same id number, same name, same type, same brand_id,same price, and a lot of null values. Is there a query which I can run which only displays columns which do not have null values?
You can select the rows that dont have null values in given columns, or you can use IFNULL.
IFNULL(yourColumn,0)
This will display 0 instead of Null, but beware that NULL and 0 is not the same thing.
Null is "nothing" / undefined, 0 is a numerical value.
You can have issues multiplying with NULL, so you can do for instance:
SELECT (numProducts * IFNULL(productPrice,0))
FROM ...
You can also use CASE or IF to select differenct colums and alias them :-)
External link to docs: https://dev.mysql.com/doc/refman/4.1/en/control-flow-functions.html
Yes above solutions will work only if that column has default value set to null,if its not set then you need to check blank ,i mean to say IFNULL(productPrice,0) will not work you need to do as below,
SELECT (numProducts * IF(productPrice='',0,productPrice))
FROM ...
You are basically asking about two problems that I will address separately in this answer.
1 - More than one record is returned
You should follow mathielo and Olavxxx's comments regarding the use of JOIN.
The query as shown in your question is a cartesian product between your tables clothing and sizing. What the query is basically asking is "I want only the record with id 101 in one of the table, as well as all the records in the other table".
Judging by the rest of your question, this is not what you want. So I take it there is a relationship between rows in clothing and sizing. I will assume that a clothing can only have one size, and that this relationship is represented by a foreign key to sizing. Here the minimum the tables should contain for that to work (I do not reuse your model because from the details in the question I can only guess, not know, what your exact table model is):
clothing:
id: primary key
size_id: foreign key to sizing
sizing:
size_id: primary key
As a consequence, the following query should return all records corresponding to the selected clothing and associated size:
SELECT *
FROM clothing AS c
JOIN sizing AS s ON c.size_id = s.size_id
WHERE c.id = 101
Your relationship between your two tables may actually be different from what I have just modeled. If that is the case, I still hope the above example is enough to get you started in the right direction.
2 - Lots of NULL values
This part of the question needs to be precised. Is it that you do not want the records with NULL values for some columns to be returned, or is it that you just do not want to get the content of these columns? Or maybe you want to use a default value?
If it is the records you want to filter out, you should add <column> IS NOT NULL conditions in your WHERE clause. One for each of the columns you are interested in.
If it is the columns you do not want to get, do not use SELECT * but instead explicitely list the columns you want, for example:
SELECT id, name, price FROM clothing
If it is about using a default value instead, you need to use IF in the SELECT clause as in Supriya's answer. Another example:
SELECT name, size, IF(shoulder IS NULL, 'Default', shoulder)
FROM clothing

SQL return only not empty columns from row as new row

I'm in the situation where my client e-mails me an excel-file with 50 columns of data extremely un-normalized. I then export it to CSV and upload into MySQL -- single table. The columns are for different ingredients (10 columns of data for each ingredient -- title, category, etc) and then 40 different columns for characteristics on each ingredients. So each ingredient in the table has all of these 50 columns even though every column doesn't apply for that ingredient.
My question is if I can create a SQL that selects only filled in characteristics for one selected ingredient and leaves out all of the other columns?
(I know that another option is to build my own CSV-parser that created multiple tables and then write SQL for them instead, but I wanna investigate solving this as is first. If that's not possible then I just have to face that and build a parser ;P)
This is as far as I came but this doesn't completely exclude columns not filled in (or that contains "nei".
SELECT
IF(`Heving-vanlig-gjaerbakst` <> '' AND `Heving-vanlig-gjaerbakst` <> 'nei', `Heving-vanlig-gjaerbakst`, 'random') AS `test1`,
IF(`Frys-kort` <> '' AND `Frys-kort` <> 'nei', `Frys-kort`, 'random') AS `test2`
... and for the 38 other rows ...
FROM x
WHERE id = 123
And I'd rather not solve this in the PHP-code by skipping empty rows =P
Example row (column names first):
g1 gruppe ug1 undergruppe artnr artikkel beskrivelse status enhet ansvar prisliste Heving-vanlig-gjaerbakst Heving-soete-deiger Deig-stabilitet Smaksgiver Saftighet Krumme-poring Skorpe Volum Konservering Skjaerbarhet Frys-lang Frys-kort Kjoel Holdbarhet E-fri Azo-fri Mandler Aprikoskjerner Helmiks Halvmiks Base Konsentrat Utstrykning Bakefasthet Frukt-Baerinnhold Slippegenskaper Hindre-koksing Palmefri Fritering Smidighet Baking Kreming Roere Fylning Dekor Prefert Viskositet Cacaoinnhold Fet-innhold
100150 Bakehjelpemidler 100150200 Fiber/potetprodukter 10085 Potetflakes sekk 15 kg Egnet til lomper, lefser, brød og annet bakverk. B... Handel Sekk Trond Olsen JA xxx xxx xxx
As you can see most columns are empty here. X, XX and XXX is a form of grade-system, but for some columns the content is instead "yes" or "no".
And as I said, the first 10 columns are information about that product, the other 40 is different characteristics (and it's those I wanna work with for one given product).
It sounds a bit as if you'd like to convert the table you have into two tables:
CREATE TABLE Ingredients
(
g1 ...,
gruppe ...,
ug1 ...,
undergruppe ...,
artnr ... PRIMARY KEY,
artikkel ...,
beskrivelse ...,
status ...,
enhet ...,
ansvar ...,
prisliste ...
);
I've opted to guess that the artnr is the primary key, but adapt what follows to the actual primary key. This table contains the eleven (though your question said ten) columns that are common to all ingredients. You then have another table which contains:
CREATE TABLE IngredientProperties
(
artnr ... NOT NULL REFERENCES Ingredients,
property VARCHAR(32) NOT NULL,
value VARCHAR(3) NOT NULL,
PRIMARY KEY(artnr, property)
);
You can then load the populated columns from your original table into these two. At worst, there'd be 40 entries in IngredientProperties for one entry in Ingredient. You might make 'property' into a foreign key reference to a defining list of possible ingredient properties (a third table that defines the possible values for the properties - basically, a record of the column names from your original table). If you add the third table, it might logically be called IngredientProperties (too), in which case the table I called IngredientProperties needs to be renamed.
You can then join Ingredients and IngredientProperties to get the information you want.
I'm not sure that I recommend this solution; it is basically a use of the 'Entity Attribute Value' approach to database design. However, for extremely sparse information like you seem to have, and when used with the constraint of the third table.
What you can't sensibly do is handle all possible combinations of 40 columns as that number grows exponentially with the number of columns (and is pretty large with N = 40).

How to Structure a Table where *some* Columns can have Multiple Values? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to Store Multiple Options selected by User in a Table
I am very confused by this.
I want my users to be able to restrict who may contact them. So I need to create a new table of RESTRICTIONS for each user and their selected criteria, which will have a column for each user's restriction criteria. Those columns will include age, income, looking for, drugs, etc. Some of those columns (looking for, drugs, etc.) might contain multiple choices, and therein lies my problem. How do I structure the table in this way, considering some criteria (columns) can have multiple values while others do not?
I've been told about join tables and enum values (both of which I've never worked with before), but I am really confused as to how I would structure a table in which some columns (not all), can contain multiple choices.
How do I store those multiple choices in those specific columns of the table and how do I structure the overall table of RESTRICTIONS?
A DB column (at least theorethically) should NOT hold multiple values. Unfortunately, there are some programmers that store multiple values in a single column (values separated by comma for examples) - those programmers (in most cases) destroy the concept of DB and SQL.
I suggest you to read about Database Normalization to get a start in organizing your tables. And, do your best to achieve the Codd's Third Normal Form
This is the simplest way. Multiple attributes become rows in a second table.
CREATE TABLE restrictions (
user_id INTEGER PRIMARY KEY, -- references users (user_id), not shown
age_restriction VARCHAR(10) NULL,
income_restriction VARCHAR(20) NULL
);
CREATE TABLE looking_for (
user_id INTEGER NOT NULL REFERENCES restrictions (user_id),
looking_for VARCHAR(35) NOT NULL, -- could also be a foreign key.
PRIMARY KEY (user_id, looking_for)
);
INSERT INTO restrictions (user_id) VALUES (1);
INSERT INTO restrictions (user_id, age_restriction) VALUES (2, '> 25');
INSERT INTO looking_for VALUES (1, 'boat');
INSERT INTO looking_for VALUES (1, 'dunky fazoo');
If you wanted to accept multiple restrictions on age, such as '> 25' and '< 55', you could build another table for that, too.
To retrieve all the restrictions, use an OUTER JOIN.
SELECT r.user_id, r.age_restriction, r.income_restriction, lf.looking_for
FROM restrictions r
LEFT JOIN looking_for lf ON lf.user_id = r.user_id
You probably need more than one table.
You have a "users" table already, right? If one of your "restrictions" criteria can have just one value per user, then that column belongs in the "users" table. So you might have columns "min_age" and "max_age" in the users table, because presumably each user has only one, contiguous range of ages they are looking for.
On the other hand, for each restriction criterion that can have multiple values, you need a new table. So you might have a table "users_restrictions_drugs" in which the primary key is (user, drug). But you might also have a table "users_restrictions_lookingfor" in which the primary key is (user, lookingfor). Whatever "looking for" is.
For some of these tables it may make sense either
to define the second column (the one that isn't "user") as an enum
or (better) to have an additional table that sets out the possible values of that second column and is referenced by a foreign key.
table restrictions
user_id smoker_ok min_height max_height min_age max_age
-------------------------------------------------------
1 Y 150 200 24 34
2 N 100 180 32 57
table drug_restrictions
user_id drug_id drug_allowed
----------------------------------
1 H N
1 M Y
2 E Y
Would be an example. In the restrictions table, you can store explicit, singular values - smokers yes or no, or min and max requirements.
For each table where there are multiple choices, you can create a join table - I've given an example for drugs.
In the drug_restrictions table, user 1 says she doesn't want people using H, but does want people using M.
This solution allows you to use the "drug_id" as a foreign key to whatever table in your database populates the "drugs" field on the user interface. It allows you to use regular, standard SQL conventions for those foreign keys, and to enforce them at the database level by declaring them as foreign keys.
The drawback is, of course, that you have to query lots of tables to find matching records, and that's not much fun.
So, you could also follow Catcall's recommendation - this dramatically reduces the number of tables, but makes it impossible to use "standard" foreign key integrity constraints. This might be okay - it's certainly going to be faster.
I'd be reluctant to use enums - they tend to lead to complex queries, and are not "standard" SQL.
There's no problem to have tables where some columns have duplicate values. Consider a tbale with users; there's no problem if two users have the same birthday?
The only problem is a table where a primary key occurs more than once. For instance, a user table may very well have username as its primary key, and you wouldn't want two users with the same username.
So, make one table that lists users, one that lists restrictions, and one that joins the two. The latter will have one entry for every combination of user/permission.

mysql query to delete records that match multiple fields

I have a database that looks like this:
CREATE TABLE cargo (
cargodate int unsigned NOT NULL,
cargoname CHAR(128) NOT NULL,
lattitude double NOT NULL,
longitude double NOT NULL,
user CHAR(64) NOT NULL
) type=MyISAM;
I want to make sure there are no more than 5 entries for this cargo at the same location with the same user. A user can have multiple entries as long as they are in different locations (lattitude, longitude).
How do I make my sql INSERT statement take care of this?
Right now I execute:
INSERT INTO cargo VALUES (UNIX_TIMESTAMP(), '{$cargoname}', '{$lat}', '{$lng}', '{$user}');
I can do a DELETE FROM, but I want to only delete entries if there are more than 5. In that case I want to delete the oldest entries
Thanks
Deshawnt
You could use triggers http://dev.mysql.com/doc/refman/5.0/en/triggers.html
Just after insert you may delete all not needed entries.
Using a trigger as mentioned by Ruslan Polutsygan would be the most natural solution.
If you don't want to mess around with them, then the alternative would be to run:
SELECT * FROM cargo ORDER BY cargodate DESC LIMIT 4,18446744073709551615
before you run an insert, and then delete the rows that are returned by that query, and then do the insert.
As a side-note, the number 18446744073709551615 was taken out of the example from the MySQL documentation:
To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter

Categories