This is my query of creation of table
CREATE TABLE `result` (
`id` int(11) NOT NULL,
`l_id` varchar(25) NOT NULL,
`lname` varchar(200) NOT NULL,
`first_prize` varchar(9) DEFAULT NULL,
`consolation_prize` varchar(9) DEFAULT NULL,
`second_prize` varchar(9) DEFAULT NULL,
`third_prize` varchar(9) DEFAULT NULL,
`fourth_prize` int(11) DEFAULT NULL,
`fifth_prize` int(11) DEFAULT NULL,
`sixth_prize` int(11) DEFAULT NULL,
`seventh_prize` int(11) DEFAULT NULL,
`eigth_prize` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
and this is the query of insertion of values
INSERT INTO `result` (`id`, `l_id`, `lname`, `first_prize`, `consolation_prize`, `second_prize`, `third_prize`, `fourth_prize`, `fifth_prize`, `sixth_prize`, `seventh_prize`, `eigth_prize`) VALUES
(1, '1', 'Win-Win', 'WO-878475', 'WO-878474', 'WO-878477', 'WO-878455', 8474, 8477, 8412, 8473, 8689),
(2, '2', 'KARUNNYA', NULL, NULL, NULL, NULL, 6, NULL, NULL, NULL, NULL),
(3, '3', 'SOUBHAGYA', 'WE-878656', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(4, '4', 'SREE SAKTHI', 'NB-750180', 'NE-750180', 'KO-594630', 'KF-678534', 6786, 4356, 2456, 4566, 7657);
the problem is, I cant insert multiple values to any of the columns such as first_prize,second_prize,third_prize etc...
How to do that ,please help me I have no idea and I am new to all these.
INSERT INTO result (id, l_id, lname, first_prize, consolation_prize, second_prize, third_prize, fourth_prize, fifth_prize, sixth_prize, seventh_prize, eigth_prize)
VALUES (1, '1', 'Win-Win', 'WO-878475,WO-878474,WO-878477', NULL,NULL, 'WO-878455', 8474, 8477, 8412, 8473, 8689);
increase the length of column.
I suggest you use "2", the last option in my answer.
i need to enter two different values(ie,WO-878475,WE-878475) in the column first_prize
To answer your question directly, you can have a delimiter between values (eg | or comma) and then when you select the field data you split based on your delimiter. This is 99% of the time a bad design approach, it really is.
I sincerely suggest that you instead consider a slight re-design and do either:
1)
Add more fields, such as first_prize_1 and first_prize_2. This is likely not the best way but I don't know all of your setup - this will make maintenance problems if you need another in the future, such as first_prize_3, but a lot better than multiple values in a single field.
2)
This is likely the better way - Make a new table prizes and have the fields:
id
prize_id
prize_level (this will be 1, 2, 3 etc for first prize and so on)
competition_id
Then just have a row per prize per competition, and select everything for the competition_id, and the fields allow you to state what prize it is, etc.
So id field is auto increment for unique row ID. Then rows would look like:
id = 1; prize_id = WO-878475; prize_level = 1; competition_id = 1;
id = 2; prize_id = WE-878475; prize_level = 1; competition_id = 1;
Then you select where competition_id = 1 and you get all the possible prizes for that competition, with the prize_id and prize_levels (1st, 2nd etc). This way, as per the above example, you can have more than one first prize, and as rows are endless you can have as many or as little prizes as you require per competition and thus are not restricted by the fields you have in a table (like field first_prize, second_prize etc).
MySQL is a relational database. I suggest you to use two tables.
The first one event will contain the event data (id and name, etc.), the second one can be structured as following:
`event_id` varchar(25) NOT NULL,
`winner` varchar(9) NOT NULL,
`prize_type` int(11) NOT NULL,
Then you can define your keys, e.g.:
0 = consolation prize
1 = first prize
2 = second prize
etc..
Related
I have the following 2 tables, api_analytics_data, and telecordia.
CREATE TABLE `api_analytics_data` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`upload_file_id` bigint(20) NOT NULL,
`partNumber` varchar(100) DEFAULT NULL,
`clei` varchar(45) DEFAULT NULL,
`description` varchar(150) DEFAULT NULL,
`processed` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_aad_clei` (`clei`),
KEY `idx_aad_pn` (`partNumber`),
KEY `id_aad_processed` (`processed`),
KEY `idx_combo1` (`partNumber`,`clei`,`upload_file_id`)
) ENGINE=InnoDB CHARSET=latin1;
CREATE TABLE `telecordia` (
`tid` int(11) NOT NULL AUTO_INCREMENT,
`ProdID` varchar(50) DEFAULT NULL,
`Mfg` varchar(20) DEFAULT NULL,
`Pn` varchar(50) DEFAULT NULL,
`Clei` varchar(50) DEFAULT NULL,
`Series` varchar(50) DEFAULT NULL,
`Dsc` varchar(50) DEFAULT NULL,
`Eci` varchar(50) DEFAULT NULL,
`AddDate` date DEFAULT NULL,
`ChangeDate` date DEFAULT NULL,
`Cost` float DEFAULT NULL,
PRIMARY KEY (`tid`),
KEY `telecordia.ProdID` (`ProdID`) USING BTREE,
KEY `telecordia.clei` (`Clei`),
KEY `telecordia.pn` (`Pn`),
KEY `telcordia.eci` (`Eci`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Users upload data via a web interface using Excel/CSV files into api_analytics_data. The data contains EITHER the partNumbers or CLEIs. I then update the api_analytics_data table by joining the telecordia table. The telecordia table is the master list of partNumber and Cleis.
So if a user uploads a file of CLEIs, the update/join I use is:
update api_analytics_data aad
inner join telecordia t on aad.clei = t.Clei
set aad.partNumber = t.Pn
where aad.partNumber is null
and aad.upload_file_id = 5;
It works quickly, but not very thoroughly. The problem I have is that the CLEI uploaded may only be a substring of the CLEI in the telecordia table.
For example, the uploaded CLEI may be "5SC1DX0". In the telcordia table, the correct matching row is:
tid: 184324
ProdID: 472467
Mfg: PLSE
Pn: AUA58-2-REV-E
Clei: 5SC1DX04AA
Series: null
Dsc: DL SGL-PTY POTS CU RT
Eci: 205756
AddDate: 1994-03-18
ChangeDate: 1998-04-13
Cost: null
So obviously my update doesn't work in this case, even though 5SC1DX0 and 5SC1DX04AA are the same part.
What I need is a wildcard search. However, when I try this, it is crazy slow. With about 4500 rows uploaded into the api_analytics_data table, it runs for about 10 minutes, and then loses the connection with the server.
update api_analytics_data aad
inner join telecordia t on aad.clei like concat(t.Clei,'%')
set aad.partNumber = t.Pn
where aad.partNumber is null
and aad.upload_file_id = 5;
Is there a way to optimize this so that it runs quickly?
The correct answer is "no". The better course of action is to create a new column in telecordia with the correct Clei value in it, one that can be used for joining the tables. In the most recent versions of MySQL, this can even be a computed column and be indexed.
That said, you might be able to do something if the matching portion is always the same length. If so, try this:
update api_analytics_data aad inner join
telecordia t
on t.Clei = left(aad.clei, 7)
set aad.partNumber = t.Pn
where aad.partNumber is null and aad.upload_file_id = 5;
For this query, you want an index on api_analytics_data(upload_fiel_id, partNumber, clei) and telecordia(clei, pn).
Let's say I have a table (tableA) with a column Kwaliteit, which will hold an int value (0, 1, 2, 3) that will represent some string values.
These string values are stored serialized in an another table (tableB) like this:
a:4:{i:0;s:4:"Goed";i:1;s:5:"Matig";i:2;s:6:"Slecht";i:3;s:12:"Afgeschreven";}
Which will give a PHP array like this:
Array
(
[0] => Goed
[1] => Matig
[2] => Slecht
[3] => Afgeschreven
)
The thing is, I want to filter on Afgeschreven. So I insert that in the LIKE part of the query, but that isn't working because there's an int instead of the string in tableA.
How can I bypass this problem? Can I like alter the column value temporarily with the string value to do the filter?
Edit
Here's the structure of tableA (Kist)
CREATE TABLE IF NOT EXISTS `Kist` (
`idKist` int(11) NOT NULL AUTO_INCREMENT,
`idKistType` int(11) NOT NULL,
`Tag1` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`Tag2` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`VisueelNr` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`Bouwjaar` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`kwaliteit` tinyint(1) NOT NULL,
`Actief` tinyint(1) NOT NULL,
PRIMARY KEY (`idKist`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=982 ;
INSERT INTO `Kist` (`idKist`, `idKistType`, `Tag1`, `Tag2`, `VisueelNr`, `Bouwjaar`, `kwaliteit`, `Actief`) VALUES
(1, 1, '0086-1700-0000-0000-0000-371E', '0086-1700-0000-0000-0000-3868', '0', '', 3, 0),
(2, 1, '0086-1700-0000-0000-0000-413F', '0086-1700-0000-0000-0000-409A', '0', '', 0, 1);
And tableB (Instellingen)
CREATE TABLE IF NOT EXISTS `Instellingen` (
`idInstellingen` int(11) NOT NULL AUTO_INCREMENT,
`Instelling` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
`Waarde` longtext COLLATE utf8_unicode_ci,
PRIMARY KEY (`idInstellingen`),
UNIQUE KEY `Instelling_UNIQUE` (`Instelling`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=220 ;
INSERT INTO `Instellingen` (`idInstellingen`, `Instelling`, `Waarde`) VALUES
(200, 'kistKwaliteit', 'a:4:{i:0;s:4:"Goed";i:1;s:5:"Matig";i:2;s:6:"Slecht";i:3;s:12:"Afgeschreven";}');
The serialized value is stored in column Waarde
What you have is supposedly more or less this:
select * from tablea where kwaliteit = 'Afgeschreven';
Which doesn't work, as kwaliteit is the code, not the string. What you are looking for is about this:
select * from tablea where kwaliteit =
(select kwaliteit from tableb where text = 'Afgeschreven');
Since you saved the mapping of ints to strings for the kwaliteit values serialised as text, it's not possible to select based on the text/label in MySQL.
What you could do, for example, is create a new table Kwaliteit, with 2 columns, id and label. Then you could join that new table with the Kist table ON Kist.kwaliteit = Kwaliteit.id
The where condition would be with those column names WHERE label = 'Afgeschreven'
Another possibility would be changing the Instellingen table: Split the Waarde column into 2, id and value. That would mean 4 rows in the table for the kwaliteit in that table:
(200, 'kistKwaliteit', '0', 'Goed'),
(200, 'kistKwaliteit', '1', 'Matig'),
(200, 'kistKwaliteit', '2', 'Slecht'),
(200, 'kistKwaliteit', '3', 'Afgeschreven')
The request could be
SELECT * FROM Kist WHERE kwaliteit =
(SELECT id FROM Instellingen WHERE Instelling = 'kistKwaliteit' AND value = 'Afgeschreven')
If you want to keep the database structure the same, you have to handle getting the ID that matches the quality you want on the PHP side. For example if it's something a user can chose via dropdown, make the value the ID as saved in the serialised array, and use the labels just as labels. Or when getting passed the string for the quality, first get the serialized array from the DB to find the ID, then use that ID in the SELECT.
You can't. You should do search by array key (aka 3 or 2), this will also speed up query.
For updated structure you can try using:
select * from Instellingen where Waarde like "%Afgeschreven%";
I've got a huge table 'books' storing book information where I plan to have a row for media type, let's call it 'media_ID'. I know that I'm dealing here with only three possible values: book, ebook and audiobook.
So, making a separate table out of this three values seems to me like wasting especially when I have to include it in every query which feels also unnecessary to me. So what's a clean solution for such cases? Maybe using a PHP array in a config file? What are you using?
books
-------
ID
media_ID
title
...
medias
-------
ID
type
MySQL data:
CREATE `books` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`media_ID` tinyint(4) NOT NULL DEFAULT '1',
`title` tinytext NOT NULL,
)
INSERT INTO `books` (`ID`, `media_ID`, `title`) VALUES
(1, 1, 'Some print book title'),
(2, 1, 'Other print book title'),
(3, 2, 'First ebook title'),
(4, 2, 'Second ebook title'),
(5, 3, 'Single audio book title');
CREATE TABLE `medias` (
`ID` tinyint(4) NOT NULL AUTO_INCREMENT,
`type` tinytext NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `medias` (`ID`, `Medium`) VALUES
(1, 'book'),
(2, 'ebook'),
(3, 'audiobook');
Or just php array:
$medias = array("book", "ebook", "audiobook");
Using a separate table for just 3 values is NOT out of the ordinary.
Furthermore this will give you the option of adding more attributes in the future-if the need arises...something that will be an issue with ENUM column type.
In my app...I have such a table that stores the payments packages the user selected...and these are only three.
So go for a table if you are not sure about your future needs/requirements.
Personally I'd use a enum for this.
`mediaType` ENUM('book', 'ebook', 'audiobook') not null
It's also possible to use lookup tables to handle enumaration. Just found the solution here: How to handle enumerations without enum fields in a database.
CREATE `books` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`media` tinyint(4) NOT NULL DEFAULT '1',
`title` tinytext NOT NULL,
FOREIGN KEY (media) REFERENCES medias(Medium)
)
I have two tables one containing a selection of values in different categories and the other ‘master’ table referencing the text values by the first primary key.
Table 1
CREATE TABLE IF NOT EXISTS `defaultvalues` (
`default_ID` int(11) NOT NULL AUTO_INCREMENT,
`columnName` varchar(100) NOT NULL,
`defaultValue` varchar(100) NOT NULL,
PRIMARY KEY (`default_ID`),
UNIQUE KEY `columnName` (`columnName`,`defaultValue`)
)
Table 2
CREATE TABLE IF NOT EXISTS `master` (
`master_ID` int(11) NOT NULL AUTO_INCREMENT,
`size` int(11) NOT NULL,
`madeby` int(11) NOT NULL,
`type` int(11) NOT NULL,
`colour` int(11) NOT NULL,
`notes` text NOT NULL,
`issueDate` datetime NOT NULL,
`ceMark` text NOT NULL,
`batchNumber` text NOT NULL,
PRIMARY KEY (master_ID)
)
The master.size for each row is a P.key in the defaultvalues table.
E.g. master.colour = 234, 234=defaultvalues.defaultValue = ‘red’
E.g. master.size = 345, 345=defaultvalues.defaultValue = ‘small’
Now I would like to run a query that returns the ‘master’ table with text values in columns colour, size, type, madeby from ‘defaultvalues. defaultValue’ and ready for further processing.
I have been trying with sub queries and temp tables but I can’t get it to work
The current system relies on PHP and multiple queries and building arrays.
There has to be a more elegant solution.
I hope this makes sense.
Any hints or advice much appreciated.
Dave
You'll need to join the master table to the defaultvalues table multiple times. Something like this:
SELECT m.*, d.defaultvalue as sizevalue, d2.defaultvalue as colorvalue...
FROM master m
JOIN defaultvalues d ON m.size = d.default_id
JOIN defaultvalues d2 ON m.color = d2.default_id
...
What i did in the end.... while it works I am still not happy. There must be something better...
SELECT m.*,
(SELECT defaultValue FROM defaultvalues WHERE default_ID = m.colour) AS myColour ,
(SELECT defaultValue FROM defaultvalues WHERE default_ID = m.size) AS mySize
FROM master m
WHERE m.master_ID = 1;
Let's assume I have three tables in my database, representing a hierarchic order:
countries, states, and cities
Each city is connected to one state, each state to one country. This is simple to represent in a database.
Let's further assume each of those tables contains a field tax_rate. In a basic case the tax rate is defined on country level and null on all other levels. However, it could be overwritten on any of the levels below.
When I query for a city node I would like to get its tax rate. It could be defined right within the same node, but more likely it will be defined on any of the next-higher levels.
What is the most efficient way to accomplish this either in MySQL or on PHP level? In my real life application there will not be only one such field but many of them.
Below is a simple database schema of my example. Of course it would also have foreign key definitions.
CREATE TABLE `countries` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`tax_rate` float(4,2) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `countries` (`id`, `tax_rate`, `name`)
VALUES
(1,8.00,'Switzerland'),
(2,16.00,'Germany');
CREATE TABLE `cities` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`state_id` int(11) DEFAULT NULL,
`tax_rate` float(4,2) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
)
NSERT INTO `cities` (`id`, `state_id`, `tax_rate`, `name`)
VALUES
(1,1,NULL,'Bern'),
(2,1,NULL,'Zollikofen'),
(3,2,NULL,'Zurich'),
(4,2,5.30,'Wettingen'),
(5,2,NULL,'Winterthur'),
(6,2,6.60,'Handligen'),
(7,3,NULL,'Bayern-Town 1'),
(8,3,NULL,'Bayern-Town 2'),
(9,3,9.00,'Bayern-Town 3');
CREATE TABLE `states` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`country_id` int(11) DEFAULT NULL,
`tax_rate` float(4,2) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `states` (`id`, `country_id`, `tax_rate`, `name`)
VALUES
(1,1,NULL,'Bern'),
(2,1,9.00,'Zurich'),
(3,2,NULL,'Bavaria');
Use COALESCE(). That's what it's for.
This could be handled on either level: MySQL or PHP
I'd prefer the MySQL approach:
select cities.name, COALESCE(cities.tax_rate,states.tax_rate,countries.tax_rate) from cities
join states on cities.state_id=states.id
join countries on states.country_id = countries.id
This will return the city's tax rate if it is not NULL, else the state's. If that also is null, it'll return the country's tax rate.