Count the number of times of component replacement - mysql

I want to find the count on "The number of times a replacement occurred for each component."
For example,
Component_ID | Replacement_ID
001 | NULL
002 | 001
003 | 002
004 | 003
005 | Null
Result :
Component_ID | Number of time a replacement already occurred
004 | 3
005 | 0

Normally you are supposed to have at-least two tables. A components table which contains your components with Component_ID as the primary field together with other fields such as component_name and another table probably called component_replacements which contains a primary field ID such as component_replacement_id together with component_id and other fields such as replacement date. Component_ids can occur more than once in this table. This would allow you to have a basic query such as:
SELECT Component_ID, IFNULL( total,0) replacements FROM
(
SELECT Component_ID, COUNT(*) total
FROM component_replacements GROUP BY Component_ID
) replacements ON components.Component_ID = replacements.Component_ID

Related

How to join multiple fields in order using mySQL query?

I have a table where it has Size and Price for each product. There could be multiple sizes with prices. I want to read size and price with ":" separated while each size:price is separated by commas for each product.
If I read it using SQL query I get the following.
PRODUCT_ID SIZE PRICE
001 L 20
001 S 15
002 M 10
002 L 20
002 S 5
I want to read the following as follows :
PRODUCT SIZE_PRICE
001 L:20,S:15
002 M:10,L:20,S:5
What is the best way to do this ?
You can try to use group_concat with CONCAT
Schema (MySQL v5.7)
CREATE TABLE T(
PRODUCT_ID varchar(50),
SIZE varchar(50),
PRICE int
);
INSERT INTO T VALUES ('001','L',20);
INSERT INTO T VALUES ('001','S',15);
INSERT INTO T VALUES ('002','M',10);
INSERT INTO T VALUES ('002','L',20);
INSERT INTO T VALUES ('002','S',5);
Query #1
SELECT PRODUCT_ID,
GROUP_CONCAT(CONCAT(SIZE,':',PRICE)) 'SIZE_PRICE'
FROM T
GROUP BY PRODUCT_ID;
| PRODUCT_ID | SIZE_PRICE |
| ---------- | ------------- |
| 001 | L:20,S:15 |
| 002 | M:10,L:20,S:5 |
View on DB Fiddle

update column if the data is null by comparing all columns

i have encountered a scenario where i want to compare the columns which are null and update the data to that column which has the 1st occurrence of null for example :
id institute_name_1 institute_name_2 institute_name_3 institute_name_4
1 xyz null null null
2 abc pqr null null
now if i want to update add the institute name of user 1 then it should be update on institute_name_2 column and if user with id 2 wants to add institute then it should be updated on institute_name_3
This is pretty bad table design. Here is suggested version of your table, using the same data:
user_id | institute_name
1 | xyz
2 | abc
2 | pqr
That is, store each relationship between a user and an institute in a separate record. Then, adding or removing relationships maps directly to adding or removing records.
If you really needed to keep track of which user/institute entry were first, second, etc., then you should probably have a dedicated column for that. Perhaps a time_inserted datetime column would make sense:
user_id | institute_name | time_inserted
1 | xyz | 2018-10-25 12:00:03
2 | abc | 2018-10-25 13:55:23
2 | pqr | 2018-10-25 14:02:00
Now the "second" institute for user #2 can be determined using the time_inserted column which provides an ordering.

Count groups in table but if any record in 2 group is same then consider it as one group only

I am woking on production database in my organisation. I have come across one scenario. Here is the sample data which I generated. Actual data is similar only, Just changed the field names.
My table structure is similar to this,
tableAi - unsigned bigint(20) - Auto increment index
loginDetails - varchar(200)
loginType - tinyint(4) (2- gmail, 3 facebook)
studentid - unsigned bigint(20)
tableAi | loginDetails | loginType | studentId
1 | abc#gmail.com | 2 | 333
2 | abc#facebook.com | 3 | 333
3 | xyz#facebook.com | 3 | 444
4 | xxx#gmail.com | 2 | 444
5 | test#gmail.com | 2 | 555
6 | abc#facebook.com | 3 | 555
7 | ac#facebook.com | 3 | 666
8 | ac#gmail.com | 2 | 777
9 | abc#facebook.com | 3 | 777
I want to count total number of students (that is very simple). But here my requirement is if loginDetail is same for 2 students then consider them as one student.
So, from above example StudentId 333, 555 and 777 have same facebook email id. So, when I count number of students, I have to consider these 2 student Ids as 1 only even though gmail account is different. So, even if one login details is same, for 2 persons, I want to treat those 2 persons as 1 person only. In production data, there is such data also that I have to consider 4-5 personIds as one person only based on their login details.
So, for above sample table, I need to generate query which returns total number of students as 3. (not 5).
Distinct student Ids will be (333,555,777) , 444 and 666
some query like tis will give you the output:
SELECT
count(*), -- only for test
GROUP_COUNCAT(t.studentId) AS stundents,
t.loginDetails,
MAX(t.loginType) as loginType,
t.studentId
FROM tableAi t
GROUP BY t.loginDetails
HAVING count(*) = 2;

Inserting sorted values from one MySQL table into another table

I have two tables, average_table and position_table. They have two column each. I would like to copy sorted data from average_table into position_table as shown below
The average_table looks like this
std_id avr
001 23.4
002 34.7
003 13.9
004 56.8
then the position_table should look like this:
std_id avr
004 56.8
002 34.7
001 23.4
003 13.9
When I used the following sql queries, the result was no different between average_table and position_table. Can some one help me out please?
try {
String str = "insert into POSITION_TABLE select * from AVERAGE_TABLE ORDER BY avr DESC";
rs = st.executeQuery(str);
}
catch(SQLException ce){System.out.print(ce)}
In the SQL world rows aren't really sorted. There might be a way to do this in MySQL (in SQL server, I think a clustered might do it - but for another reason than getting the rows in order).
In other words, an inserted row is not guaranteed to have a specific order. As SQL is declarative, you have to declare how to order it when you query.
I don't understand what you're trying to achieve with the position table - to me it looks like an exact duplicate of the average table and you're getting the data in ranked order already with your query using the order by. Just use order by when you need the data ordered.
create table average_table
( std_id int not null,
avr decimal(8,2) not null
);
insert average_table (std_id,avr) values (1,23.4),(2,34.7),(3,13.9),(4,56.8);
create table position_table
( id int auto_increment primary key,
std_id int not null,
avr decimal(8,2) not null
);
insert into position_table(std_id,avr) select std_id,avr from average_table order by avr desc;
select * from position_table;
+----+--------+-------+
| id | std_id | avr |
+----+--------+-------+
| 1 | 4 | 56.80 |
| 2 | 2 | 34.70 |
| 3 | 1 | 23.40 |
| 4 | 3 | 13.90 |
+----+--------+-------+

How To Design A Database for a "Check In" Social Service

I want to build a "check in" service like FourSquare or Untappd.
How do I design a suitable database schema for storing check-ins?
For example, suppose I'm developing "CheeseSquare" to help people keep track of the delicious cheeses they've tried.
The table for the items into which one can check in is fairly simple and would look like
+----+---------+---------+-------------+--------+
| ID | Name | Country | Style | Colour |
+----+---------+---------+-------------+--------+
| 1 | Brie | France | Soft | White |
| 2 | Cheddar | UK | Traditional | Yellow |
+----+---------+---------+-------------+--------+
I would also have a table for the users, say
+-----+------+---------------+----------------+
| ID | Name | Twitter Token | Facebook Token |
+-----+------+---------------+----------------+
| 345 | Anne | qwerty | poiuyt |
| 678 | Bob | asdfg | mnbvc |
+-----+------+---------------+----------------+
What's the best way of recording that a user has checked in to a particular cheese?
For example, I want to record how many French cheeses Anne has checked-in. Which cheeses Bob has checked into etc. If Cersei has eaten Camembert more than 5 times etc.
Am I best putting this information in the user's table? E.g.
+-----+------+------+--------+------+------+---------+---------+
| ID | Name | Blue | Yellow | Soft | Brie | Cheddar | Stilton |
+-----+------+------+--------+------+------+---------+---------+
| 345 | Anne | 1 | 0 | 2 | 1 | 0 | 5 |
| 678 | Bob | 3 | 1 | 1 | 1 | 1 | 2 |
+-----+------+------+--------+------+------+---------+---------+
That looks rather ungainly and hard to maintain. So should I have separate tables for recordings check in?
No, don't put it into the users table. That information is better stored in a join table which represents a many-to-many relationship between users and cheeses.
The join table (we'll call cheeses_users) must have at least two columns (user_ID, cheese_ID), but a third (a timestamp) would be useful too. If you default the timestamp column to CURRENT_TIMESTAMP, you need only insert the user_ID, cheese_ID into the table to log a checkin.
cheeses (ID) ⇒ (cheese_ID) cheeses_users (user_ID) ⇐ users (ID)
Created as:
CREATE TABLE cheeses_users
cheese_ID INT NOT NULL,
user_ID INT NOT NULL,
-- timestamp defaults to current time
checkin_time DATETIME DEFAULT CURRENT_TIMESTAMP,
-- (add any other column *specific to* this checkin (user+cheese+time))
--The primary key is the combination of all 3
-- It becomes impossible for the same user to log the same cheese
-- at the same second in time...
PRIMARY KEY (cheese_ID, user_ID, checkin_time),
-- FOREIGN KEYs to your other tables
FOREIGN KEY (cheese_ID) REFERENCES cheeses (ID),
FOREIGN KEY (user_ID) REFERENCES users (ID),
) ENGINE=InnoDB; -- InnoDB is necessary for the FK's to be honored and useful
To log a checkin for Bob & Cheddar, insert with:
INSERT INTO cheeses_users (cheese_ID, user_ID) VALUES (2, 678);
To query them, you join through this table. For example, to see the number of each cheese type for each user, you might use:
SELECT
u.Name AS username,
c.Name AS cheesename,
COUNT(*) AS num_checkins
FROM
users u
JOIN cheeses_users cu ON u.ID = cu.user_ID
JOIN cheeses c ON cu.cheese_ID = c.ID
GROUP BY
u.Name,
c.Name
To get the 5 most recent checkins for a given user, something like:
SELECT
c.Name AS cheesename,
cu.checkin_time
FROM
cheeses_users cu
JOIN cheeses c ON cu.cheese_ID = c.ID
WHERE
-- Limit to Anne's checkins...
cu.user_ID = 345
ORDER BY checkin_time DESC
LIMIT 5
Let's define more clearly, so you can tell me if I'm wrong:
Cheese instances exist and aren't divisible ("Cheddar/UK/Traditional/Yellow" is a valid checkinable cheese, but "Cheddar" isn't, nor is "Yellow" or "Cheddar/France/...)
Users check into a single cheese instance at a given time
Users can re-check into the same cheese instance at a later date.
If this is the case, then to store fully normalized data, and to be able to retrieve that data's history, you need a third relational table linking the two existing tables.
+-----+------------+---------------------+
| uid | cheese_id | timestamp |
+----+-------------+---------------------+
| 345 | 1 | 2014-05-04 19:04:38 |
| 345 | 2 | 2014-05-08 19:04:38 |
| 678 | 1 | 2014-05-09 19:04:38 |
+-----+------------+---------------------+
etc. You can add extra columns to correspond to the cheese data, but strictly speaking you don't need to.
By putting all this in a third table, you potentially improve both performance and flexibility. You can always reconstruct the additions to the users table you mooted, using aggregate queries.
If you really decide you don't need the timestamps, then you'd replace them with basically the equivalent of a COUNT(*) field:
+-----+------------+--------------+
| uid | cheese_id | num_checkins |
+----+-------------+--------------+
| 345 | 1 | 15 |
| 345 | 2 | 3 |
| 678 | 1 | 8 |
+-----+------------+--------------+
That would dramatically reduce the size of your joining table, although obviously there's less of a "paper trail", should you need to reconstruct your data (and possibly say to a user "oh, yeah, we forgot to record your checkin on such-a-date.")
The entities 'User' and 'Cheese' have a many-to-many relationship. A user can have multiple cheeses he checked into, and a cheese can have multiple people that checked into it.
The only right way to design this in a relational database is to store it into a separate table. There are many reasons why storing it into the user table for instance, is a very bad idea. Read up on normalizing databases for more info on this.
Your table should look something like this:
CheckIns(CheeseId, UserId, (etc...))
Other useful columns might include date or rating, or whatever you want to store about a particular relationship between a user and a cheese.