How to select a column with specific column value in SQL 2008? - sql-server-2008

I have table T1 containing two columns id and decision. id may be repeating for various decision. Please refer the example below:
Table T1:
|---------------------|------------------|
| id | decision |
|---------------------|------------------|
| abc_0011 | Forward |
|---------------------|------------------|
| abc_0011 | Forward |
|---------------------|------------------|
| abc_0011 | Reject |
|---------------------|------------------|
| abc_0012 | Forward |
|---------------------|------------------|
| abc_0012 | Forward |
|---------------------|------------------|
Required Table:
|---------------------|------------------|
| id | decision |
|---------------------|------------------|
| abc_0011 | Reject |
|---------------------|------------------|
| abc_0012 | Pending |
|---------------------|------------------|
Here there are two distinct id abc_011 and abc_012, abc_011 appears three time, with different decision where the last decision is Reject while abc_012 appears two times, where both the decision are forward and there is no decision like Reject. Idea is to construct a table where the id which at any stage is rejected must display reject and the id which is not rejected in any case must display pending. Note: the id must not repeat in the final table.

Below code should give you the expected results.
;WITH CTE AS (
SELECT ID,MAX(DECISION) DECISION
FROM T1
GROUP BY ID
)
SELECT ID,CASE WHEN DECISION!='Reject' THEN 'Pending' ELSE DECISION END DECISION
FROM CTE

Related

How to check if there are some recordings share the same name, but they have different types in mysql

There is a table with 97972561 rows (recordings) and 4 columns (attributes). The format looks like:
+------+-------------+-------------+-------------+
| PMID | SUBJECT_NAME| SUBJECT_TYPE| Sentence_ID |
+------+-------------+-------------+-------------+
I would like to check if there are some subjects share the same name with different types.
For example, there are three recordings in a table:
+------+-------------+-------------+-------------+
| PMID | SUBJECT_NAME| SUBJECT_TYPE| Sentence_ID |
+------+-------------+-------------+-------------+
| 1 | Bob | F | 1 |
+------+-------------+-------------+-------------+
| 2 | Bob | B | 2 |
+------+-------------+-------------+-------------+
| 3 | Bob | F | 3 |
+------+-------------+-------------+-------------+
I do not care about how many cases, just want to check if there are two recordings with the same subject_name, but different subject_type. Any help would be appreciated!
I would aggregate by subject name and then assert that the max and min types are different:
SELECT SUBJECT_NAME
FROM yourTable
GROUP BY SUBJECT_NAME
HAVING MIN(SUBJECT_TYPE) <> MAX(SUBJECT_TYPE);
Note the way I wrote the HAVING clause leaves it sargable, meaning that any index on SUBJECT_TYPE could potentially be used. The following index might speed up this query:
CREATE INDEX idx ON yourTable (SUBJECT_NAME, SUBJECT_TYPE);

How to design one-to-many relationship tables considering update operation?

I may appoint some specific receivers when new a notice. So I design one-to-many tables named notice and receiver:
mysql> select * from notice;
+----+-------+
| id | title |
+----+-------+
| 1 | demo |
+----+-------+
mysql> select * from receiver;
+----+-----------+--------+
| id | notice_id | name |
+----+-----------+--------+
| 1 | 1 | calvin |
| 2 | 1 | john |
+----+-----------+--------+
When I update the notice, the receivers might be updated too(Assuming the receivers should be updated to calvin and Jack). My current solution is deleting all receivers related to the notice and inserting the new ones. Is there any better and higher-performance solution? I can redesign the tables if it's necessary.

Inserting data from a join within tables

I'm trying to figure out how to extend a table of company_ids using a group reference from another table. For a given company_name, I want to get its company_ids, join them with the company_groups table, and get their group_ids. From there, I want to get every company_id associated with the group_id, and insert them in the companies table with the proper company_name.
The structure is a bit atypical. A single company name can have many IDs, because the ID isn't used as a unique identifier for a single company. I'm trying to make sure all of them get copied to the companies table. I'm sure there's a fairly simple join command, but I've never been very good at joining tables within themselves. Can anyone help? Thanks!
+---------------+
| companies |
+---------------+
| company_id PK |
| company_name |
+---------------+
+----------------+
| company_groups |
+----------------+
| company_id PK |
| group_id |
+----------------+
Here's an example. In the companies table, I have the company "Tesla", with three different IDs.
+--------------+------------+
| company_name | company_id |
+--------------+------------+
| Tesla | 647552 |
| Tesla | 927572 |
| Tesla | 748563 |
+--------------+------------+
In the company_groups table, each group_id has one or more company_ids.
+----------+------------+
| group_id | company_id |
+----------+------------+
| 227 | 647552 |
| 227 | 111743 |
| 227 | 111842 |
+----------+------------+
I want to match the company_name to multiple group_ids, then find all company_ids associated with the group. The new company_ids would then be inserted in the companies table like this:
+--------------+------------+
| company_name | company_id |
+--------------+------------+
| Tesla | 647552 |
| Tesla | 927572 |
| Tesla | 748563 |
| Tesla | 111743 |
| Tesla | 111842 |
+--------------+------------+
You cannot insert into a table when the same table name appear in the where clause.
You can use a temporary third table to do this job
At second thought, your question is either funny or not clear enough, please provide your sample data, so that i can update my answer
I figured it out. A nested query works well:
REPLACE INTO companies (company_name, company_id)
SELECT a.company_name, company_groups.company_id
FROM
(
SELECT group_id, company_groups.company_id, companies.company_name
FROM companies
JOIN company_groups
ON companies.company_id=company_groups.company_id
GROUP BY group_id
) a
JOIN company_groups
ON company_groups.group_id=a.group_id
GROUP BY company_id;

Confusion in creating table design

I am using Mysql and I have two tables-
BusDetails
+-------+-----------+
| busId | BusName |
+-------+-----------+
| 1 | A TRAVELS |
| 2 | B TRAVELS |
| 3 | C TRAVELS |
+-------+-----------+
AreaDetails
+--------+----------+
| cityId | cityName |
+--------+----------+
| 1 | ABC |
| 2 | DEF |
| 3 | GHI |
| 4 | JKL |
+--------+----------+
Now I have to create third table which will map bus table to city table. Suppose busId 1 stops at cityId 2 and 3 and bustId 2 stops at cityId 1 and 4. To create this scenario I have 2 options-
first option-
+-------+--------+
| busId | areaId |
+-------+--------+
| 1 | 3,2 |
| 2 | 4,1 |
+-------+--------+
second option-
+-------+--------+
| busId | areaId |
+-------+--------+
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 4 |
+-------+--------+
In future when there will be large number of records then which table will give better performance and why ?
The first option is poor because comma-separated lists do not get indexed. If you want to find all the busses in area 2, you would have to use
SELECT busID
FROM bus_areas
WHERE FIND_IN_SET('2', areaID)
This will have to perform a full table scan, parse the areaID column on each row, and test whether 2 is a member of the resulting array.
With the second version you can do:
SELECT busID
FROM bus_areas
WHERE areaID = 2
If you have an index on areaID, this will be extremely efficient.
If you wanted to know how many busses are in each area, it's easy with the second option:
SELECT areaID, COUNT(*)
FROM bus_areas
GROUP BY areaID
With the first option it would be more cumbersome:
SELECT cityID, COUNT(*)
FROM areaDetails a
JOIN bus_areas ba ON FIND_IN_SET(a.cityID, ba.areaID)
GROUP BY cityID
This will be very inefficient because it has to perform M*N FIND_IN_SET operations, and as I explained above this cannot be indexed. Notice that I had to join with the areaDetails table because there's no way to enumerate all the areas in the comma-separated lists in SQL.
The answer depends upon your use.
Although first option is not recommended but if you have very large data and you are not planning to perform wide range of Database operations (probably for self or small project) you can use it.
Second options has it's own advantage and recommended by relational model. It will give you more flexibility and scalability as this minimize redundancy.
Dear Second Table Is Better For All Reason Baecause At long time you have big data second type in save so many rows but better for getting report easy in easy for SQL query easy. you can all type join easy.

MySQL Multi Duplicate Record Merging

A previous DBA managed a non relational table with 2.4M entries, all with unique ID's. However, there are duplicate records with different data in each record for example:
+---------+---------+--------------+----------------------+-------------+
| id | Name | Address | Phone | Email | LastVisited |
+---------+---------+--------------+---------+------------+-------------+
| 1 | bob | 12 Some Road | 02456 | | |
| 2 | bobby | | 02456 | bob#domain | |
| 3 | bob | 12 Some Rd | 02456 | | 2010-07-13 |
| 4 | sir bob | | 02456 | | |
| 5 | bob | 12SomeRoad | 02456 | | |
| 6 | mr bob | | 02456 | | |
| 7 | robert | | 02456 | | |
+---------+---------+--------------+---------+------------+-------------+
This isnt the exact table - the real table has 32 columns - this is just to illustrate
I know how to identify the duplicates, in this case i'm using the phone number. I've extracted the duplicates into a seperate table - there's 730k entires in total.
What would be the most efficient way of merging these records (and flagging the un-needed records for deletion)?
I've looked at using UPDATE with INNER JOIN's, but there are several WHERE clauses needed, because i want to update the first record with data from subsequent records, where that subsequent record has additional data the former record does not.
I've looked at third party software such as Fuzzy Dups, but i'd like a pure MySQL option if possible
The end goal then is that i'd be left with something like:
+---------+---------+--------------+----------------------+-------------+
| id | Name | Address | Phone | Email | LastVisited |
+---------+---------+--------------+---------+------------+-------------+
| 1 | bob | 12 Some Road | 02456 | bob#domain | 2010-07-13 |
+---------+---------+--------------+---------+------------+-------------+
Should i be looking at looping in a stored procedure / function or is there some real easy thing i've missed?
U have to create a PROCEDURE, but before that
create ur own temp_table like :
Insert into temp_table(column1, column2,....) values (select column1, column2... from myTable GROUP BY phoneNumber)
U have to create the above mentioned physical table so that u can run a cursor on it.
create PROCEDURE myPROC
{
create a cursor on temp::
fetch the phoneNumber and id of the current row from the temp_table to the local variable(L_id, L_phoneNum).
And here too u need to create a new similar_tempTable which will contain the values as
Insert into similar_tempTable(column1, column2,....) values (Select column1, column2,.... from myTable where phoneNumber=L_phoneNumber)
The next step is to extract the values of each column u want from similar_tempTable and update into the the row of myTable where id=L_id and delete the rest duplicate rows from myTable.
And one more thing, truncate the similar_tempTable after every iteration of the cursor...
Hope this will help u...