remove view duplicate data in sql database - sql

SELECT ticket_id, thread_type, FROM ost_ticket_thread WHERE thread_type='M'
this is my sql statement. the result from the sql statement like below.
-----------------------
|ticket_id|thread_type|
-----------------------
|4 | M |
|4 | M |
|5 | M |
-----------------------
How i want to view data without the same ticket_id and thread_type?
i have done the group by statement. but i have encounter a problem when i want to count all ticket_id. it should be 2. but it return 3.

Try GROUP BY:
SELECT ticket_id, thread_type
FROM ost_ticket_thread
WHERE thread_type='M'
GROUP BY ticket_id,thread_type
OR
Use DISTINCT:
SELECT DISTINCT ticket_id, thread_type
FROM ost_ticket_thread
WHERE thread_type='M'
Result:
TICKET_ID THREAD_TYPE
4 M
5 M
Sample result in SQL Fiddle.
EDIT:
For the getting the count:
SELECT ticket_id, thread_type,COUNT(ticket_id) as Count
FROM ost_ticket_thread
WHERE thread_type='M'
GROUP BY ticket_id,thread_type
Result:
TICKET_ID THREAD_TYPE COUNT
4 M 2
5 M 1

Use this query
SELECT distinct(ticket_id), thread_type, FROM ost_ticket_thread WHERE thread_type='M';
this will work

Related

Oracle issue in group by

I know this question is asked by many people. But I still couldn't figure out why this is happening. Couldn't understand this logic.
I have a table mytesttable with columns id, company_name and employee_name.
I am trying to get the employee details grouping them with respect to company name. So I used the below query:
select *
from mytesttable
group by company_name;
But I get the below issue:
ORA-00979: not a GROUP BY expression
00979. 00000 - "not a GROUP BY expression"
*Cause:
*Action:
Error at Line: 28 Column: 2
Now I have tried putting count(1) in select along with my columns, tried grouping using 2 columns etc. Still the same issue. Can anyone explain me how to achieve this?
Because this is a simple group by. Logic seems to be right, but wondering why it's not fetching me the result.
Your query is:
select *
from mytesttable
group by company_name;
The * expands to all the columns. So this becomes:
select company_name, col1, col2, col3, . . . -- your question doesn't specify the column names
from mytesttable
group by company_name;
When you specify the group by, you are specifying that there is one row per company_name in the result set. The other columns are normally filled with aggregation functions, such as MIN(), SUM(), or LISTAGG().
What value should be chosen for col1? In general, SQL does not attempt to answer this question. Instead, it returns a syntax error. This is not Oracle-specific. This is the definition of the language.
What you probably want is:
select company_name, count(*) as num_employees
from mytesttable
group by company_name;
In group by clause you have to put all selected columns. As you select all but given only one column in group by as a result it thrown error, but if you simply try like this way it will work. Actually group by used for aggregated function
select company_name, count(*) from mytesttable group by company_name;
I think you mis-understand what GROUP BY does?
It doesn't put all similar records next to each other, that's ORDER BY. What GROUP BY does is to collapse all similar records in to the same row, to allow aggregate calculations like SUM() and MIN() and COUNT(), etc.
So, two examples using the same input...
id | company_name | employee_name
----+--------------+---------------
1 | zzz | aaa
2 | xxx | bbb
3 | yyy | ccc
4 | zzz | ddd
5 | xxx | eee
Using ORDER BY...
SELECT * FROM mytesttable ORDER BY company_name, employee_name
id | company_name | employee_name
----+--------------+---------------
2 | xxx | bbb
5 | xxx | eee
3 | yyy | ccc
1 | zzz | aaa
4 | zzz | ddd
Using GROUP BY...
SELECT
company_name,
COUNT(*) number_of_employees,
MAX(id) highest_id_in_company
FROM
mytesttable
GROUP BY
company_name
ORDER BY
company_name
company_name | number_of_employees | highest_id_in_company
--------------+---------------------+-----------------------
xxx | 2 | 5
yyy | 1 | 3
zzz | 2 | 4
If you use group-by expression,you have to use aggregate functions such as max,min,average,count in select statements.
For example;
select count(*),company_name,employee_name
from mytesttable
group by company_name,employee_name
order by company_name;

Iterating over groups in table

I have the following data:
cte1
===========================
m_ids |p_id |level
---------|-----------|-----
{123} |98 |1
{123} |111 |2
{432,222}|215 |1
{432,222}|215 |1
{432,222}|240 |2
{432,222}|240 |2
{432,222}|437 |3
{432,222}|275 |3
I have to perform the following operation:
Extract p_id by the following algorithm
For every row with same m_ids
In each group:
2.I. Group records by p_id
2.II. Order desc records by level
2.III. Select p_id with exact count as the m_ids length and with the biggest level
So far I fail to write this algorithm completely, but I wrote (probably wrong where I'm getting array_length) this for the last part of it:
SELECT id
FROM grouped_cte1
GROUP BY id,
level
HAVING Count(*) = array_length(grouped_cte1.m_ids, 1)
ORDER BY level DESC
LIMIT 1
where grouped_cte1 for m_ids={123} is
m_ids |p_id |level
---------|-----------|-----
{123} |98 |1
{123} |111 |2
and for m_ids={432,222} is
m_ids |p_id |level
---------|-----------|-----
{432,222}|215 |1
{432,222}|215 |1
{432,222}|240 |2
{432,222}|240 |2
{432,222}|437 |3
{432,222}|275 |3
etc.
2) Combine query from p.1 with the following. The following extracts p_id with level=1 for each m_ids:
select m_ids, p_id from cte1 where level=1 --also selecting m_ids for joining later`
which results in the following:
m_ids |p_id
---------|----
{123} |98
{432,222}|215
Desirable result:
m_ids |result_1 |result_2
---------|-----------|--------
{123} |111 |98
{432,222}|240 |215
So could anyone please help me solve the first part of algorithm and (optionally) combine it in a single query with the second part?
EDIT: So far I fail at:
1. Breaking the presented table into subtables by m_ids while iterating over it.
2. Performing computation of array_length(grouped_cte1.m_ids, 1) for corresponding rows in query.
For the first part of the query you're on the right track, but you need to change the grouping logic and then join again to the table to filter it out by highest level per m_ids for which you could use DISTINCT ON clause combined with proper sorting:
select
distinct on (t.m_ids)
t.m_ids, t.p_id, t.level
from cte1 t
join (
select
m_ids,
p_id
from cte1
group by m_ids, p_id
having count(*) = array_length(m_ids, 1)
) as g using (m_ids, p_id)
order by t.m_ids, t.level DESC;
This would give you:
m_ids | p_id | level
-----------+------+-------
{123} | 111 | 2
{432,222} | 240 | 2
And then when combined with second query (using FULL JOIN for displaying purposes, when the first query is missing such conditions) which I modified by adding distinct since there can be (and in fact is) more than one record for m_ids, p_id pair with first level it would look like:
select
coalesce(r1.m_ids, r2.m_ids) as m_ids,
r1.p_id AS result_1,
r2.p_id AS result_2
from (
select
distinct on (t.m_ids)
t.m_ids, t.p_id, t.level
from cte1 t
join (
select
m_ids,
p_id
from cte1
group by m_ids, p_id
having count(*) = array_length(m_ids, 1)
) as g using (m_ids, p_id)
order by t.m_ids, t.level DESC
) r1
full join (
select distinct m_ids, p_id
from cte1
where level = 1
) r2 on r1.m_ids = r2.m_ids
giving you result:
m_ids | result_1 | result_2
-----------+----------+----------
{123} | 111 | 98
{432,222} | 240 | 215
that looks different from what you've expected but from my understanding of the logic it is the correct one. If I misunderstood anything, please let me know.
Just for the sake of logic explanation, one point:
Why m_ids with {123} returns 111 for result_1?
for group of m_ids = {123} we have two distinct p_id values
both 98 and 111 account for the condition of equality count with the m_ids length
p_id = 111 has a higher level, thus is chosen for the result_1

Count and max aggregate function in same table in one query

I have to do count and max aggregate function in same query. For example I have history table contains date column. I need to retrieve the latest date as well as count () with some criteria. Criteria is applicable for only count() . I am able to retrieve the latest date using max and rank function.But could not merge both. Could you please assist?
Update:
Scenario : Customer buys/sells Shares.
Input: Table Share_history and Table Customer and Table Share and Table Share_Status
Customer :
Cust_id |Cust_name
1 |A
2 |B
Share :
Share_id|Share_Name|Owner|
10 |ABC |XYZ |
20 |BCD |MNC |
Share_Status :
Share_Status_Id|Share_Status_Name
1 |Buy
2 |Sell
Share_history :
Share_history _id|Share_id|Trans_date|Share_status_Id|Cust_id
100 |10 |12/12/14 | 1 |1
101 |10 |24/12/14 | 2 |1
102 |10 |14/01/15 | 1 |1
103 |10 |28/02/15 | 2 |1
103 |10 |16/03/15 | 1 |1
Output: latest Trans_date and count(no of times specific share was bought(1)) and Cust_id=1.
Query:
select share1.Share_id,SHAREHIST.Latest_Date,SHAREHIST.buycount
from Share share1 left outer join
(select share_id,max(Trans_date) keep(dense_rank last order by share_id) as Latest_Date,
(select count(*) as buycount from Share_history where Share_status_id=1 and Share_id=share1.Share_id)
from Share_history
group by Share_id
) SHAREHIST
on SHAREHIST.share_id=share1.share_id
EXPECTED :
Share_id|Latest_Date|buycount
10 |16/03/15 | 3
Try using this:
SELECT
Share_id
,Trans_Date
,COUNT(Share_id) buycount
FROM
(
SELECT
*
FROM Share_history SH
WHERE Trans_Date = (SELECT MAX(Trans_Date) FROM Share_history)
) SH
GROUP BY Share_id, Trans_Date
Rest of the joins I think you can add.
I think you just want aggregation:
select sh.share_id, max(trans_date) as trans_date, count(*) as buy_count,
from share_history sh
where cust_id = 1
group by sh.share_id;

How to select records with order id in SQLite

I have a query that selects data in an alphabetical order. For example:
ID |TITLE
6 |A
35 |AA
3 |B
87 |BB
...
And I would like to select an order id of the record as well (order id it's not an actual column in the db). So the result should look like:
ID |ORDER ID |TITLE
6 |0 |A
35 |1 |AA
3 |2 |B
87 |3 |BB
...
How can I achieve something like this? I could check every returned record in a while loop and I would increase a counter on every iteration but that's not really what I want to do and I would rather leave this on database.
This is kind RANK function in other database engines.
In SQLite, you can achieve this like:
SELECT ID, (SELECT COUNT() FROM table AS t WHERE Title<table.Title), Title FROM table;
dense_rank and sqlite - possible?
EDIT: Distinct order numbers:
SELECT ID, (SELECT COUNT() FROM table AS t WHERE Title<table.Title OR Title=table.Title AND ROWID<table.ROWID), Title FROM table;
Something like this:
SELECT * FROM yourtable WHERE id = 3 ORDER BY title
This will return all fields in yourtable (id, order id, title) where the id column is 3
Edited to add:
Additional information from comment - include order_id in result set but not from table. To to this you can add a constant and alias the column like so:
SELECT id, '999' AS order_id, title FROM yourtable WHERE id = 3 ORDER BY title
This will return an order_id column with 999 as the value.

Accessing column alias in postgresql

Having a little bit of trouble understanding how a query alias works in postgresql.
I have the following:
SELECT DISTINCT robber.robberid,
nickname,
Count(accomplices.robberid) AS count1
FROM robber
INNER JOIN accomplices
ON accomplices.robberid = robber.robberid
GROUP BY robber.robberid,
robber.nickname
ORDER BY Count(accomplices.robberid) DESC;
robberid | nickname | count1
----------+--------------------------------+--------
14 | Boo Boo Hoff | 7
15 | King Solomon | 7
16 | Bugsy Siegel | 7
23 | Sonny Genovese | 6
1 | Al Capone | 5
...
I can rename the "count1" column using the as command but I can't seem to be able to refer to this again in the query? I am trying to include a HAVING command at the end of this query to query only objects who have a count less than half of the max.
This is homework but I am not asking for the answer only a pointer to how I can include the count1 column in another clause.
Can anyone help?
In general, you can't refer to an aggregate column's alias later in the query, and you have to repeat the aggregate
If you really want to use its name, you could wrap your query as a subquery
SELECT *
FROM
(
SELECT DISTINCT robber.robberid, nickname, count(accomplices.robberid)
AS count1 FROM robber
INNER JOIN accomplices
ON accomplices.robberid = robber.robberid
GROUP BY robber.robberid, robber.nickname
) v
ORDER BY count1 desc