I got a table structure in my HTML
Needs to populate the data as rows and columns, some columns having a value "1"
Fixed 10 Rows and 10 Columns and there are multiple tables
So I just created a database like the following
ga_id (pk) | A1 | A2 | A3 ......
-------------+-------+------+-------------
125 | 1 | 0 | 0 ..........
-------------+-------+------+--------------
126 | 0 | 1 | 1 ...
I got the following questions
For achieving the same, is my approach is correct ?
I need to check whether a column or a row is fully occupied with a value "1"
for eg:-
Case block D4 then I need to check D1,D2,D3..... D10 having the same value ie 1
And A4,B4,C4,D4.......J4 values having the same value
Hope my question is clear,
By way of example, a normalised environment might look something like this:
CREATE TABLE my_table
(id INT NOT NULL
,x INT NOT NULL
,y CHAR(1) NOT NULL
,val INT NOT NULL
,PRIMARY KEY(id,x,y)
);
INSERT INTO my_table VALUES
(101,2,'B',1),
(101,2,'I',1),
(101,4,'D',1),
(101,5,'I',1),
(101,7,'D',1),
(101,7,'H',1),
(101,8,'G',1);
As a comment, the "correct approach" is whatever approach solves your issue. While normalization and the third normal form are concepts that are battle tested and definitely worth mastering, if the current structure solves your particular issue, go with it.
A possible, normalized DB structure would be:
Table columns: column_id, name
Table rows: row_id, name
Table tables: table_id, name
Table table_rows_columns: table_id, row_id,
column_id, value
Related
Database has two tables with same schema.
date VARCHAR(20),
track VARCHAR(150),
race_number INT,
horse_number INT,
early_last5 FLOAT(10,1),
PRIMARY KEY (track, race_number, horse_number, date)
One is named sectional_table and another is window_sectional_table.
I want to copy all contents of sectional table to window_sectional_table.
I do the most logical thing possible.
INSERT INTO window_sectional_table SELECT * FROM sectional_table;
Unfortunately, I am terrorized by this error.
Data truncated for column 'early_last5' at row 1
I investigate row 1. Row 1 looks like this.
+------------+----------+-------------+--------------+-------------+
| date | track | race_number | horse_number | early_last5 |
+------------+----------+-------------+--------------+-------------+
| 2021-05-03 | GUNNEDAH | 1 | 1 | 0.0 |
+------------+----------+-------------+--------------+-------------+
How do I proceed? I believe the value 0.0 should have been auto filled for null value.
The Data truncated for column 'early_last5' at row 1 error is referring to your INSERT statement rather than which specific value in the database is being truncated.
I believe the value 0.0 should have been auto filled for null value.
Nope. That’s not defined in your INSERT and it’s not defined in the table creation statement.
How do I proceed?
The simplest method would be to convert the FLOAT value to a DECIMAL for the INSERT, complete with an IFNULL if you want NULL to be converted to 0.0. The FLOAT data type has long been a thorn in the side of many people who expect it to work like a typical decimal.
Here’s a quick SQL statement that should get you moving again:
INSERT INTO `window_sectional_table` (`date`, `track`, `race_number`, `horse_number`, `early_last5`)
SELECT `date`, `track`, `race_number`, `horse_number`,
CAST(IFNULL(`early_last5`, 0) AS DECIMAL(10,1))
FROM `sectional_table`
ORDER BY `track`, `race_number`, `horse_number`, `date`;
I have a table like below:
ID|Prototype_A|Prototype_B|Prototype_C|Prototype_D|
---------------------------------------------------
1 |Fast381A |Blue4812 | Green7181 | White4812 |
---------------------------------------------------
2 |Slow841C |Orange8312 | null | null |
---------------------------------------------------
3 |Plane281K | null | null | null |
---------------------------------------------------
I need my query to return all non null prototypes for that ID.
so for example:
1 : Fast381A,Blue4812,Green7181,White4812
2 : Slow841C,Orange8312
3 : Plane281K
Is there a way to wildcard select all columns like select(Prototype_*) or should I setup my table in a different format?
For example I've been taught this type of structure is bad practice:
ID|Prototypes|
---------------------------------------------------
1 |Fast381A,Blue4812,Green7181,White4812
---------------------------------------------------
2 |Slow841C,Orange8312
---------------------------------------------------
3 |Plane281K
---------------------------------------------------
A SQL query returns a fixed set of columns. If you want to combine the non-NULL values into a single column, I would recommend concat_ws():
select id,
concat_ws(',', Prototype_A, Prototype_B, Prototype_C, Prototype_D)
from t;
This ignores the NULL values. The query returns two columns, one is a list of prototypes.
And, the answer to your question is "Yes". You should consider changing your data structure. Having multiple columns storing the same thing, with just an index identifying them usually means that you want a separate table, with one row per id and per prototype.
EDIT:
You want a table like this:
create table ModelPrototypes (
ModelProtypeId int primary key auto_increment,
ModelId int not null,
ProtoTypeChar char(1),
Prototype varchar(255)
);
Then you would populate it with values like:
1 A Fast381A
1 B Blue4812
1 C Green7181
1 D White4812
I'm not sure if PrototypeChar is really needed, but the information is in your table.
There's no way to wildcard select columns.
What you could do:
Setup your table as
ID, Prototype_type, Prototype_name
Then use GROUP_CONCAT:
SELECT id, GROUP_CONCAT(Prototype_name SEPARATOR ',')
FROM table GROUP BY Prototype_name
"Should I setup my table in a different format?"
Yes. Your table might look as follows:
ID Prototype_Code Prototype
------------------------------
1 A Fast381A
1 B Blue4812
1 C Green7181
1 D White4812
2 A Slow841C
2 B Orange8312
3 A Plane281K
My head is already spinning from this and I need your help.
MY DATABASE
imported CSV file: 22 columns and 11k rows
2 tables with the same data (both created from the CSV)
Added ID as PRIMARY KEY to both
All VARCHAR(60) Some columns are empty strings ' '
DB:
PID | CODE 1 | CODE 2 | CODE 3 | CODE 4 | CODE 5 | CODE X (up to 9) | ID
-------------------------------------------------------------------------
1 | a | b | c | | | | 1
2 | a | | b | d | | | 2
3 | x | | | | | y | 3
DB has 22 columns but I'm only including CODE columns (up to 9)
in which I might be interested in terms of SQL statement.
It'll be only read table - MyISAM engine then?
WHAT I'D LIKE TO DO
select PID = 1 from first table
and retrieve all PIDs from second table
IF
selected PID's column CODE 1
or
selected PID's column CODE 2 (which is b) etc (up to 9).
= any PID's CODE X
So I should get only PID 2.
edit: PID is not a ID, it's just an example code, it could be string: '002451' and I'm looking for other PIDs with the same CODES (e.g PID1 has code = a so it should find PID2 becasue one of its CODE columns contains a)
MY ATTEMPT
SELECT a.* FROM `TABLE1` a WHERE
(
SELECT * FROM `TABLE2` b WHERE b.`PID` = 1
AND
(
( b.`CODE 1` NOT IN ('') AND IN (a.`CODE 1`,a.`CODE 2`, A.`CODE 3`...) ) OR
( b.`CODE 2` NOT IN ('') AND (a.`CODE 1`,a.`CODE 2`, A.`CODE 3`...) ) OR...
I'd end up with large query - over 81 conditions. In terms of performance... well, it doesn't work.
I intuitively know that I should:
use INDEXES (on CODE 1 / CODE 2 / CODE 3 etc.?)
use JOIN ON (but I'm too stupid) - that's why I created 2 tables (let's assume I don't want TEMP. TABLES)
How to write the SQL / design the DB efficently?
The correct data structure is one row per pid and code. The simplest way is:
create table PCodes (
pid int not null,
code varchar(255),
constraint fk_PCodes_pid references p(pid)
);
Then you have the values in a single column and it is much simpler to check for matching codes.
In practice, you should have three tables:
create table Codes (
CodeId int not null auto_increment primary key,
Code varchar(255)
);
create table PCodes (
pid int not null,
codeid int not null,
constraint fk_PCodes_pid references p(pid),
constraint fk_PCodes_codeid references codes(codeid);
);
If the ordering of the codes is important for each "p", then include a priority or ordering column in the PCodes table.
I have a report table that looks similar to this
reports
inspection_type | inspection_number
berries | 111
citrus | 222
grapes | 333
inspection_type in my case is the name of the other table I would like
to SELECT * from where the inspection_number equals report_key on
that associated table.
{fruit}
row | report_key | etc....
value | 111 | value
value | 222 | value
The issue is I do not know how to query inspection_type to get the table name
to query the value. Does that make any sense?
I tried this here, but even I know that it's glaringly wrong:
SELECT inpection_type, inspection_number
FROM reports rpt
ON rpt.inspection_number = report_key
(SELECT * FROM inspection_type WHERE status < '2')
WHERE rpt.status < '2'
ORDER BY rpt.inspection_number DESC
Could a SQL guru tell me the best way to do this?
Since it is not possible to have a variable for a table name directly in TSQL, you will have to dynamically construct the TSQL.
Variable table names in Stored Procedures
You can't really do what you are aiming to in SQL alone, you'll need to either mess around in another language, or (and this is the preferred solution) restructure the database i.e. (sorry for the meta-code)
// Comes in where your existing `reports` table is
inspections (
inspection_id INT UNSIGNED NOT NULL AI,
inspection_type_id INT UNSIGNED NOT NULL (links to inspection_types.inspection_type_id)
.... other rows ....
)
// New table to normalise the inspection types
inspection_types (
inspection_type_id INT UNSIGNED NOT NULL AI,
type_name VARCHAR NOT NULL
.... other rows ....
)
// Normalised table to replace each {fruit} table
inspection_data (
inspection_data_id INT UNSIGNED NOT NULL AI,
inspection_id INT UNSIGNED NOT NULL (links to inspections.inspection_id)
.... other rows ....
)
Then your query would be simply
SELECT *
FROM inspections
INNER JOIN inspection_types
ON inspection_types.inspection_type_id = inspections.inspection_type_id
INNER JOIN inspection_data
ON inspection_data.inspection_id = inspections.inspection_id
The brief overview above is quite vague because your existing table data hasn't really been specified, but the general principle is sound. It wouldn't even take much to migrate data out of your existing structure, but when it's done it'll give you far cleaner queries and allow you to actually get the data you're after out more easily
My problem is: I have a table with an auto_increment column. When I insert some values, all is right.
Insert first row : ID 1
Insert second row : ID 2
Now I want to insert a row at ID 10.
My problem is, that after this there are only rows inserted after ID 10 (which is the normal behaviour ).
But I want that the database first fills up ID 3-9 before making that.
Any suggestions?
EDIT:
To clarify: this is for an URL shortener I want to build for myself.
I convert the id to a word(a-zA-z0-9) for searching, and for saving in the database I convert it to a number which is the ID of the table.
The Problem is now:
I shorten the first link (without a name) -> ID is 1 and the automatically name is 1 converted to a-zA-Z0-9 which is a
Next the same happenes -> ID is 2 and the name is b, which is 2 converted.
Next interesting, somebody want to name the link test -> ID is 4597691 which is the converted test
Now if somebody adds another link with no name -> ID is 4597692 which would be tesu because the number is converted.
I want that new rows will be automatically inserted at the last gap that was made (here 3)
You could have another integer column for URL IDs.
Your process then might look like this:
If a default name is generated for a link, then you simply insert a new row, fill the URL ID column with the auto-increment value, then convert the result to the corresponding name.
If a custom name is specified for a URL, then, after inserting a row, the URL ID column would be filled with the number obtained from converting the chosen name to an integer.
And so on. When looking up for integer IDs, you would then use the URL ID column, not the table auto-increment column.
If I'm missing something, please let me know.
You could do 6 dummy inserts and delete/update them later as you need. The concept of the auto increment, by design, is meant to limit the application's or user's control over the number to ensure a unique value for every single record entered into the table.
ALTER TABLE MY_TABLE AUTO_INCREMENT = 3;
You would have to find first unused id, store it as user variable, use as id for insert.
SELECT #id := t1.id +1
FROM sometable t1 LEFT JOIN sometable t2
ON t2.id = t1.id +1 WHERE t2.id IS NULL LIMIT 1;
INSERT INTO sometable(id, col1, col2, ... ) VALUES(#id, 'aaa', 'bbb', ... );
You will have to run both queries for every insert if you still have gaps, its up to you to decide whether it is worth doing it.
not 100% sure what you're trying to achieve but something like this might work:
drop table if exists foo;
create table foo
(
id int unsigned not null auto_increment primary key,
row_id tinyint unsigned unique not null default 0
)
engine=innodb;
insert into foo (row_id) values (1),(2),(10),(3),(7),(5);
select * from foo order by row_id;
+----+--------+
| id | row_id |
+----+--------+
| 1 | 1 |
| 2 | 2 |
| 4 | 3 |
| 6 | 5 |
| 5 | 7 |
| 3 | 10 |
+----+--------+
6 rows in set (0.00 sec)