SQL Server : return 3 items - sql

Short version: I need to return a query with 3 items from another table and adding it to the existing table.
Long version:
Table A contains the following information:
| ID | Name | Date | Comment |
--------------------------------
| 1 | AJ | 9/11 | Howdy |
| 2 | AW | 9/13 | Hi |
| 3 | AK | 9/15 | Aloha |
| 4 | AW | 9/15 | Hello |
| 5 | AJ | 9/18 | Greetings |
I need Table B to resemble:
| ID | Comment | Comment2 | Comment3 |
--------------------------------------------
| 1 | Howdy | Aloha | Greetings |
I am running
SELECT TOP 3 *
FROM a
WHERE Name IN ('AJ','AK')
but that makes Table B appear like:
| ID | Name | Date | Comment |
--------------------------------
| 1 | AJ | 9/11 | Howdy |
| 3 | AK | 9/15 | Aloha |
| 5 | AJ | 9/18 | Greetings |
Is it even possible to get what I want?

Not entirely sure what you are after as you have id's for each comment, then your output has a single row with an id (where does this id come from for your output?) but this may be able to be expanded upon:
SELECT
[1] AS COMMENT1,
[2] AS COMMENT2,
[3] AS COMMENT3
FROM
TABLE_A
PIVOT (MAX(COMMENT) FOR id IN ([1],[2],[3])) AS PVT

Please try this , it helpful to you
select b.id, b.comment as comment
, (select comment from ##temp1 where id = b.id+2 ) as comment1
, (select comment from ##temp1 where id = b.id+4 ) as comment2
from ##temp1 b where b.id=1

I don't know if this will work, but i'm just throwing the idea here. Let me know if it works!
Insert into B Values (
( SELECT TOP 3 comment FROM a WHERE Name IN ('AJ','AK') limit 1 ),
( SELECT TOP 3 comment FROM a WHERE Name IN ('AJ','AK') limit 1,1 ),
( SELECT TOP 3 comment FROM a WHERE Name IN ('AJ','AK') limit 2,1 )
)
This is for MySQL. please change accordingly for MSSQL Server

Related

Joining table on two columns only joins it on a single

How do I correctly join a table on two columns. My issue is that the result is not correct as it only joins on a single column.
This question started of in this other question: SQL query returns product of results instead of sum . I am creating a new question as there is an other issue I am trying to solve.
I join a table of materials on a table which contains multiple supply and disposal movements. Each movement references a material id. I would like to join the material on each movement.
My query:
SELECT supply_material_refer, disposal_material_refer, material_id, material_name
FROM "construction_sites"
JOIN projects ON construction_sites.project_refer = projects.project_id
JOIN addresses ON construction_sites.address_refer = addresses.address_id
cross join lateral ( select *
from (select row_number() over () as rn, *
from supplies
where supplies.supply_project_refer = projects.project_id) as supplies
full join (select row_number() over () as rn, *
from disposals
where disposals.disposal_project_refer = projects.project_id
) as disposals
on (supplies.rn = disposals.rn)
) as combined
LEFT JOIN materials material ON combined.disposal_material_refer = material.material_id
OR combined.supply_material_refer = material.material_id
WHERE (projects.project_name = 'Project 15')
ORDER BY construction_site_id asc;
The result of the query:
+-----------------------+-------------------------+-------------+---------------+
| supply_material_refer | disposal_material_refer | material_id | material_name |
+-----------------------+-------------------------+-------------+---------------+
| 1 | 1 | 1 | Materialtest |
| 2 | 1 | 1 | Materialtest |
| 2 | 1 | 2 | Dirt |
| 1 | 1 | 1 | Materialtest |
| 2 | 1 | 1 | Materialtest |
| 2 | 1 | 2 | Dirt |
| 1 | (null) | 1 | Materialtest |
| 4 | (null) | 4 | Stones |
+-----------------------+-------------------------+-------------+---------------+
An example line I have issues with:
+------------------------+-------------------------+-------------+---------------+
| supply_material_refer | disposal_material_refer | material_id | material_name |
+------------------------+-------------------------+-------------+---------------+
| 2 | 1 | 1 | Materialtest |
+------------------------+-------------------------+-------------+---------------+
A prefered output would be like:
+------------------------+----------------------+-------------------------+------------------------+
| supply_material_refer | supply_material_name | disposal_material_refer | disposal_material_name |
+------------------------+----------------------+-------------------------+------------------------+
| 2 | Dirt | 1 | Materialtest |
+------------------------+----------------------+-------------------------+------------------------+
I have created a sqlfiddle with dummy data: http://www.sqlfiddle.com/#!17/863d78/2
To my understanding the solution would be to have a disposal_material column and and supply_material column for the material names. I do not know how I can achieve this goal though...
Thanks for any help!

How can I subtract two row's values within same column using sql query in access?

(query access)
This is the table structure:
+-----+--------+--------+
| id | name | sub1 |
+-----+--------+--------+
| 1 | ABC | 6.27% |
| 2 | ABC | 7.47% |
| 3 | PQR | 3.39% |
| 4 | PQR | 2.21% |
+-----+--------+--------+
I want to subtract Sub1
Output should be:
+-----+--------+---------+------------------------------------+
| id | name | sub1 | |
+-----+--------+---------+------------------------------------+
| 1 | ABC | 6.27% | 0 First Rec no need Subtract |
| 2 | ABC | 7.47% | 1.2% <=(7.47-6.27) |
| 3 | PQR | 3.39% | 0 First Rec no need Subtract |
| 4 | PQR | 2.21% | -1.18% <=(2.21-3.39) |
+-----+--------+---------+------------------------------------+
Thank you so much.
If you can guarantee consecutive id values, then the following presents an alternative:
select t.*, nz(t.sub1-u.sub1,0) as sub2
from YourTable t left join YourTable u on t.name = u.name and t.id = u.id+1
Change YourTable to the name of your table.
This is painful, but you can do:
select t.*,
(select top 1 t2.sub1
from t as t2
where t2.name = t.name and t2.id < t.id
order by t2.id desc
) as prev_sub1
from t;
This gives the previous value or NULL for the first row. You can just use - for the subtraction.
An index on (name, id) would help a bit with performance. However, if you can upgrade to a better database, you can then just use lag().

ORACLE Not In on Multiple Columns

Kindly have a look at the following structure.
Table: A
+---------+----------+
| Col1A | Col2A |
+---------+----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 1 | 2 |
| 2 | 2 |
+---------+----------+
Table: B
+---------+----------+
| Col1B | Col2B |
+---------+----------+
| 2 | 1 |
| 3 | 1 |
+---------+----------+
Here is what I am trying to achieve that is to get the result as following:
Result
+---------+----------+
| Col1A | Col2A |
+---------+----------+
| 1 | 1 |
| 4 | 1 |
| 1 | 2 |
| 2 | 2 |
+---------+----------+
What I want :
I want to get the result of table A records which are not exists in Table B. It should be on the basis of both column. If the combination exist in first table then don't no show it.
What I have tried so far :
The first approach that I have tried was to use Not In statement. Following is my statement.
SELECT A.COL1A, A.COL2A
FROM A
WHERE A.COL1A NOT IN (
SELECT B.COL1B FROM B
);
But the issue with this approach didn't consider the second column. It will give me the following result.
+---------+----------+
| 1 | 1 |
| 4 | 1 |
+---------+----------+
While it will not show following as it should be sub-traced because of we didn't checked for other column.
+---------+----------+
| 1 | 2 |
| 2 | 2 |
+---------+----------+
Then I tried Not Exists but I didn't worked too. Here is my query.
SELECT A.COL1A, A.COL2A
FROM A
WHERE NOT EXISTS(
SELECT B.COL1B,B.COL2B FROM B
);
Edit
Sorry I forget to include the fiddle link.
Here it is : Fiddle Demo
For using Exists I think you should use it like this:
SELECT *
FROM A
WHERE
NOT EXISTS(SELECT 1
FROM B
WHERE A.Col1A = B.Col1B AND A.Col2A = B.Col2B)
One way to do this which is conceptually simple is to JOIN tables A and B on the two columns, and then SELECT only those rows in A which do not exist in B:
SELECT *
FROM A
LEFT OUTER JOIN B
ON (A.COL1A = B.COL1B AND A.COL2A = B.COL2B)
WHERE B.COL1B IS NULL
SELECT *
FROM a
WHERE (col1a, col2a) NOT IN (SELECT col1b, col2b FROM b);
But be aware that this will fail if either col1b or col2b contains NULL values.
SQLFiddle DEMO
SELECT A.COL1A, A.COL2A
FROM A
WHERE (Col1A, Col2A) NOT IN (
SELECT Col1B, Col2B FROM B
);
You can even use:
SELECT A.COL1A, A.COL2A
FROM A
WHERE (Col1A, Col2A) NOT IN (
(2, 1),
(3, 1)
);

Remove dulicate rows using SQL

I want to know if there is a way to remove duplicate values from a table. The key 'distinct' will fetch us the unique rows however if one value differs in a column, it wont. so just wanted to know if this can be achieved by any means. Hope the below example will help.
For example : In the below table there are two entries for Emp_ID 1234 with two different priorities. my output should consider the higher priority row alone. Is it possible?
My table
+---------+------+--------+-------+
| Employee_ID| priority | gender |
+------------+-----------+--------+
| 1234 | 1 | F |
| 1234 | 10 | F |
| 5678 | 2 | M |
| 5678 | 25 | M |
| 9101 | 45 | F |
+------------+-----------+--------+
Output
+---------+------+--------+-------+
| Employee_ID| priority | gender |
+------------+-----------+--------+
| 1234 | 1 | F |
| 5678 | 2 | M |
| 9101 | 45 | F |
+------------+-----------+--------+
DELETE
FROM Table t
WHERE EXISTS ( SELECT Employee_ID FROM Table WHERE Employee_ID = t.Employee_ID AND priority < t.Priority)
That is if you really want to remove them from the table. The Exists part can also be used in a select query to leave the values in the Original table.
SELECT *
FROM Table t
WHERE NOT EXISTS (SELECT Employee_ID FROM Table WHERE Employee_ID = t.Employee_ID AND priority > t.Priority)
select Employee_ID,max(priority) as priority,gender
from table
group by Employee_ID,gender

PostgreSQL select all from one table and join count from table relation

I have two tables, post_categories and posts. I'm trying to select * from post_categories;, but also return a temporary column with the count for each time a post category is used on a post.
Posts
| id | name | post_category_id |
| 1 | test | 1 |
| 2 | nest | 1 |
| 3 | vest | 2 |
| 4 | zest | 3 |
Post Categories
| id | name |
| 1 | cat_1 |
| 2 | cat_2 |
| 3 | cat_3 |
Basically, I'm trying to do this without subqueries and with joins instead. Something like this, but in real psql.
select * from post_categories some-type-of-join posts, count(*)
Resulting in this, ideally.
| id | name | count |
| 1 | cat_1 | 2 |
| 2 | cat_2 | 1 |
| 3 | cat_3 | 1 |
Your help is greatly appreciated :D
You can use a derived table that contains the counts per post_category_id and left join it to the post_categories table
select p.*, coalesce(t1.p_count,0)
from post_categories p
left join (
select post_category_id, count(*) p_count
from posts
group by post_category_id
) t1 on t1.post_category_id = p.id
select post_categories.id, post_categories.name , count(posts.id)
from post_categories
inner join posts
on post_category_id = post_categories.id
group by post_categories.id, post_categories.name