forum.bitel.ru
http://forum.bitel.ru/

вывести значения двух одинаковых полей
http://forum.bitel.ru/viewtopic.php?f=19&t=10886
Страница 1 из 1

Автор:  skyb [ 12 сен 2015, 17:50 ]
Заголовок сообщения:  вывести значения двух одинаковых полей

Есть таблица log_session_{mid}_yyyyMM
там есть записи cdr_id имеющие одинаковые значения
нужно вывести поля если значения совпали, не могу догнать как, подскажите

Автор:  skyb [ 12 сен 2015, 17:52 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

можно не мускулом, можно и явой, вложеные запросы, подзапросы в одном запросе работают очень медленно

Автор:  Phricker [ 12 сен 2015, 22:13 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

вложенные запросы и подзапросы.
Мама моя...


Код:
SELECT cdr_id, COUNT(id)
FROM log_session_10_201509
GROUP BY cdr_id
HAVING COUNT(id) >1

Автор:  skyb [ 13 сен 2015, 06:48 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

Phricker писал(а):
вложенные запросы и подзапросы.
Мама моя...


Код:
SELECT cdr_id, COUNT(id)
FROM log_session_10_201509
GROUP BY cdr_id
HAVING COUNT(id) >1

не, мне нужны данные в обоих столбцах

есть код, то что выводит в отчет пока не важно, это эксперементы, вот его хотелось бы оптимизировать, выполняется он долго

Код:
package ru.skyb.reports;

import ru.bitel.common.Utils;
import ru.bitel.common.model.Period;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Calendar;

import bitel.billing.common.TimeUtils;
import ru.bitel.bgbilling.common.BGException;
import ru.bitel.bgbilling.kernel.tariff.common.bean.TariffPlan;
import bitel.billing.server.admin.reports.BGReportFilter;
import bitel.billing.server.contract.bean.PaymentManager;
import bitel.billing.server.npay.bean.ServiceObject;
import bitel.billing.server.npay.bean.ServiceObjectManager;
import bitel.billing.server.phone.bean.ClientItem;
import bitel.billing.server.phone.bean.ClientItemManager;
import bitel.billing.server.reports.BGCSVReport.ReportResult;
import bitel.billing.server.contract.bean.ContractTariffManager;

public class CustomClientsMarj implements
      bitel.billing.server.reports.BGCSVReport.CSVFillerData {
   @Override
   public void fillReport(Connection con, BGReportFilter filter,
         ReportResult result) throws SQLException, BGException {
      int j = 0;
      int NPAY_MID = 9;
      StringBuilder sb = new StringBuilder ();
      ServiceObjectManager som = new ServiceObjectManager( con, NPAY_MID ) ;
      ServiceObject srv = new ServiceObject();
      BigDecimal allCost = BigDecimal.ZERO;
      BigDecimal allCount = BigDecimal.ZERO;
      BigDecimal allCount_oper = BigDecimal.ZERO;
      ClientItemManager cim = new ClientItemManager(con, 12);
      String text = filter.getStringParam("text");
      int combo = filter.getIntParam("combo");
      Calendar month = filter.getCalendarParam( "month" );
      String yyyy = TimeUtils.format ( month, "yyyy" );
      String mm = TimeUtils.format ( month, "MM" );
      String yyyyMM = yyyy+mm;
      int time = 0;
      java.util.Date date1 = filter.getDateParam("date1");
      java.util.Date date2 = filter.getDateParam("date2");
      String groups = "3"; // коды групп договоров через запятую
      long groupMask = Utils.enumToMask(groups);
      List<Map<String, String>> data = new ArrayList<Map<String, String>>(1000);
      Map<String, String> map = new HashMap<String, String>();
      if (!text.equals("") && !text.isEmpty())
         {
            String query = " SELECT c.id, c.title, c.comment, c.date1, ls.cost, ls.cdr_id, ls.session_time, ls.session_start FROM contract AS c "
                  + " LEFT JOIN log_session_12_"+yyyyMM+" AS ls ON ls.cid = c.id"
                  + " WHERE gr&(" + groupMask + ")>0 AND c.id IN (1758,1846) AND ls.session_time > 2 "
                  //+ " WHERE gr&(" + groupMask + ")>0 AND ls.session_time > 2 "
                  + " AND scid = -1 AND title REGEXP '"+text+"'";
            sb.append(query);
         }
      else
         {
            String query = " SELECT c.id, c.title, c.comment, c.date1, ls.cost, ls.cdr_id, ls.session_time, ls.session_start FROM contract AS c "
                  + " LEFT JOIN log_session_12_"+yyyyMM+" AS ls ON ls.cid = c.id"
                  + " WHERE gr&("+ groupMask + ")>0 AND ls.session_time > 2 AND c.id IN (1758,1846) AND scid = -1 ORDER BY cdr_id";
                  //+ " WHERE gr&("+ groupMask + ")>0 AND ls.session_time > 2 AND scid = -1 ORDER BY cdr_id";
            sb.append(query);
         }
      PreparedStatement ps = con.prepareStatement(sb.toString());
      ResultSet rs = ps.executeQuery();
      while (rs.next())
         {
            Map<String, String> NewMap = new HashMap<String, String>();
            //System.out.println("query " + sb.toString());
            j++;
            //BigDecimal cost_oper = BigDecimal.ZERO;
            BigDecimal cost = BigDecimal.ZERO;
            BigDecimal cost_oper = BigDecimal.ZERO;
            int cid = rs.getInt(1);
            String title = rs.getString(2);
            String comment = rs.getString(3);
            Date dt = rs.getDate(4);
            int cdr_id = rs.getInt(6);
            //BigDecimal cost = rs.getBigDecimal(5);
            time = time + rs.getInt(7);
            NewMap.put( "cid", String.valueOf( cid ) );
            NewMap.put("title", title);
            NewMap.put("comment", comment);
            //map.put("time", String.valueOf(rs.getInt(7)) + " время сессии " + rs.getString(8));
            //map.put("count", String.valueOf(j));
            if (cid != 588)
            {
            System.out.println("cdr_id " + cdr_id + " cdr_id_oper " + cdr_id);
            }
            
            String query = "SELECT cost, session_start FROM log_session_12_"+yyyyMM+" AS ls "
                  + "WHERE cid = 588 AND cdr_id = " + cdr_id;
            PreparedStatement psq = con.prepareStatement(query);
            ResultSet rsq = psq.executeQuery();
               while (rsq.next())
               {

                  cost_oper = rsq.getBigDecimal(1);
                  System.out.println("cost  " + rs.getBigDecimal(5).toString() + " cost_oper " + cost_oper + " cdr_id " + cdr_id + "\n\n");
                  NewMap.put("count", rs.getBigDecimal(5).toString() );
                  NewMap.put("count_oper", cost_oper.toString());
                  NewMap.put("time", rs.getString(8));
                  cost = rs.getBigDecimal(5).subtract(cost_oper);
               }
            NewMap.put("cost", cost.toString());
            allCost = allCost.add(cost);   
            allCount = allCount.add(rs.getBigDecimal(5));
            allCount_oper = allCount_oper.add(cost_oper);
            
            Map<String, String> NewMap2 = new HashMap<String, String>();
            NewMap2.put("count", allCount.toString());
            NewMap2.put("count_oper", allCount_oper.toString());
            data.add(NewMap2);
            
            data.add(NewMap);   
         }
      int Time = time/60;

      //Map<String, String> map = new HashMap<String, String>();
      map.put("cost", allCost.toString());
      map.put("count", allCount.toString());
      map.put("count_oper", allCount_oper.toString());
      map.put("time", String.valueOf(Time) + " минут");
      //map.put("cost", allCost.toString());
      data.add(map);      
      result.setData(data);
   }

}

Автор:  vkulakov [ 14 сен 2015, 12:49 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

Если договоров очень много, то создавать каждый раз PreparedStatement внутри цикла будет очень накладно. Как минимум нужно вынести создание PS из цикла:
Код:
      ...
      [b]String query = "SELECT cost, session_start FROM log_session_12_"+yyyyMM+" AS ls WHERE cid = 588 AND cdr_id = ?;";[/b]
      [b]PreparedStatement psq = con.prepareStatement(query);[/b]

      PreparedStatement ps = con.prepareStatement(sb.toString());
      ResultSet rs = ps.executeQuery();
      while (rs.next())
         {
            [b]psq.setInt(1, cdr_id);[/b]
            ResultSet rsq = psq.executeQuery();
               while (rsq.next())
               {

                  cost_oper = rsq.getBigDecimal(1);
                  System.out.println("cost  " + rs.getBigDecimal(5).toString() + " cost_oper " + cost_oper + " cdr_id " + cdr_id + "\n\n");
                  NewMap.put("count", rs.getBigDecimal(5).toString() );
                  NewMap.put("count_oper", cost_oper.toString());
                  NewMap.put("time", rs.getString(8));
                  cost = rs.getBigDecimal(5).subtract(cost_oper);
               }
            NewMap.put("cost", cost.toString());
            allCost = allCost.add(cost);   
            allCount = allCount.add(rs.getBigDecimal(5));
            allCount_oper = allCount_oper.add(cost_oper);
           
            Map<String, String> NewMap2 = new HashMap<String, String>();
            NewMap2.put("count", allCount.toString());
            NewMap2.put("count_oper", allCount_oper.toString());
            data.add(NewMap2);
           
            data.add(NewMap);   
         }
      int Time = time/60;

      //Map<String, String> map = new HashMap<String, String>();
      map.put("cost", allCost.toString());
      map.put("count", allCount.toString());
      map.put("count_oper", allCount_oper.toString());
      map.put("time", String.valueOf(Time) + " минут");
      //map.put("cost", allCost.toString());
      data.add(map);     
      result.setData(data);
   }


Если договоров мало (два, как у вас в примере), а выполняется всё-равно долго, то нужно в таблицу добавить индексы, но это может сильно замедлить вставку строк. Попробуйте скопировать таблицу, добавить индексы для полей, по которым фильтруете, сортируете и т. п. и запустить отчёт на копии.

P. S. Это общие советы по увеличению производительности. У меня нет таблицы log_session, поэтому попробовать не могу.

Автор:  Phricker [ 14 сен 2015, 14:44 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

А ещё можно мой запрос вывести в temporary table и потом джойнить её.
Проверить не могу ибо на больничном

Автор:  skyb [ 14 сен 2015, 15:27 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

Phricker писал(а):
А ещё можно мой запрос вывести в temporary table и потом джойнить её.
Проверить не могу ибо на больничном

а можешь в лоб подсказать как это делать? я там расковыряю

Автор:  Phricker [ 14 сен 2015, 18:07 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

тут есть пример с временными таблицами и джойнами в них

Автор:  skyb [ 25 сен 2015, 12:01 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

с темповой таблицей ускорило, но не добился нужного результата, подскажите тогда какие индерксы вставить и как сделать? и вроде бы как можно явой проверять есть ли индексы и создавать если их нет и не создавать если они есть

Автор:  Phricker [ 25 сен 2015, 12:38 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

На тесте.

Смотришь индексы в таблице
Код:
show index from log_session_10_201509;
+-----------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table                 | Non_unique | Key_name      | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| log_session_10_201509 |          0 | PRIMARY       |            1 | id            | A         |      330444 |     NULL | NULL   |      | BTREE      |         |               |
| log_session_10_201509 |          1 | session_start |            1 | session_start | A         |      330444 |     NULL | NULL   |      | BTREE      |         |               |
| log_session_10_201509 |          1 | log           |            1 | source_id     | A         |          15 |     NULL | NULL   |      | BTREE      |         |               |
| log_session_10_201509 |          1 | log           |            2 | hour          | A         |         299 |     NULL | NULL   |      | BTREE      |         |               |
| log_session_10_201509 |          1 | cid           |            1 | cid           | A         |        6234 |     NULL | NULL   |      | BTREE      |         |               |
| log_session_10_201509 |          1 | sid           |            1 | sid           | A         |           7 |     NULL | NULL   |      | BTREE      |         |               |
| log_session_10_201509 |          1 | item_id       |            1 | item_id       | A         |        9179 |     NULL | NULL   |      | BTREE      |         |               |
+-----------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
7 rows in set (0.00 sec)


Добавляешь нужные тебе индексы.
Смотришь уменьшилось ли время выполнения.
Возможно поможет индекс на cdr_id

Автор:  skyb [ 30 сен 2015, 09:30 ]
Заголовок сообщения:  Re: вывести значения двух одинаковых полей

продолжаем =)
не могу догнать как вывести подсчет по каждому договору, по всем сделал, а как по каждому, подскажите плиз

Код:
package ru.skyb.reports;

import ru.bitel.common.Utils;
import ru.bitel.common.model.Period;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Calendar;

import bitel.billing.common.TimeUtils;
import ru.bitel.bgbilling.common.BGException;
import ru.bitel.bgbilling.kernel.tariff.common.bean.TariffPlan;
import bitel.billing.server.admin.reports.BGReportFilter;
import bitel.billing.server.contract.bean.PaymentManager;
import bitel.billing.server.npay.bean.ServiceObject;
import bitel.billing.server.npay.bean.ServiceObjectManager;
import bitel.billing.server.phone.bean.ClientItem;
import bitel.billing.server.phone.bean.ClientItemManager;
import bitel.billing.server.reports.BGCSVReport.ReportResult;
import bitel.billing.server.contract.bean.ContractTariffManager;

public class CustomClientsMarj implements
      bitel.billing.server.reports.BGCSVReport.CSVFillerData {
   @Override
   public void fillReport(Connection con, BGReportFilter filter,
         ReportResult result) throws SQLException, BGException {
      int j = 0;

      int NPAY_MID = 9;
      StringBuilder sb = new StringBuilder ();
      String TABLE_GROUPED_PHONE_ACCOUNT = "_phone_account_upload_";//Группа для выборки всех договоров и звонков по ним,
                                                      //дальше приджойнить к выборке по операторскому договору
      ServiceObjectManager som = new ServiceObjectManager( con, NPAY_MID ) ;
      ServiceObject srv = new ServiceObject();
      BigDecimal allCost = BigDecimal.ZERO;
      BigDecimal allCount = BigDecimal.ZERO;
      BigDecimal allCount_oper = BigDecimal.ZERO;
      ClientItemManager cim = new ClientItemManager(con, 12);
      String text = filter.getStringParam("text");
      int combo = filter.getIntParam("combo");
      Calendar month = filter.getCalendarParam( "month" );
      String yyyy = TimeUtils.format ( month, "yyyy" );
      String mm = TimeUtils.format ( month, "MM" );
      String yyyyMM = yyyy+mm;
      int time = 0;
      java.util.Date date1 = filter.getDateParam("date1");
      java.util.Date date2 = filter.getDateParam("date2");
      String groups = "3"; // коды групп договоров через запятую
      long groupMask = Utils.enumToMask(groups);
      
      con.createStatement().executeUpdate( "DROP TEMPORARY TABLE IF EXISTS "   + TABLE_GROUPED_PHONE_ACCOUNT);
      //con.createStatement().executeUpdate( "DROP TEMPORARY TABLE IF EXISTS _phone_account_upload_");
      
      
      String query_temp = "CREATE TEMPORARY TABLE " + TABLE_GROUPED_PHONE_ACCOUNT + " ( `id` int(11) NOT NULL, `cdr_id` int(11) NOT NULL, `hour` datetime NOT NULL, " +
      //String query_temp = "CREATE TEMPORARY TABLE _phone_account_upload_ ( `cdr_id` int(11) NOT NULL," +
        " `summa` decimal(10,2) NOT NULL, PRIMARY KEY  (`id` ) ) SELECT id, cdr_id, ROUND(cost,2) AS summa, hour " +
        " FROM log_session_12_"+yyyyMM+" "
      + " WHERE cid IN (580, 581, 588) AND session_time > 2 LIMIT 1000 ";
      PreparedStatement psCreateTempTable = con.prepareStatement(query_temp);
      psCreateTempTable.executeUpdate();
      psCreateTempTable.close();
      
      List<Map<String, String>> data = new ArrayList<Map<String, String>>(1000);
      Map<String, String> map = new HashMap<String, String>();
      if (!text.equals("") && !text.isEmpty())
         {
            String query = " SELECT c.id, c.title, c.comment, ls.cost, ls.session_time, ls.session_start, ROUND(tgpa.summa,2), ls.to_number, ls.cdr_id FROM contract AS c "
                  + " LEFT JOIN log_session_12_"+yyyyMM+" AS ls ON ls.cid = c.id "
                  + " LEFT JOIN " + TABLE_GROUPED_PHONE_ACCOUNT + " AS tgpa ON ls.cdr_id = tgpa.cdr_id AND ls.hour = tgpa.hour "
                  //+ " WHERE gr&(" + groupMask + ")>0 AND c.id IN (1758,1846) AND ls.session_time > 2 "
                  + " WHERE gr&(" + groupMask + ")>0 AND ls.session_time > 2 "
                  //+ " AND scid = -1 AND title REGEXP '"+text+"' AND ls.to_number = 79271716905";
                  + " AND scid = -1 AND title REGEXP '"+text+"' ORDER BY c.id LIMIT 1000";
            sb.append(query);
         }
      else
         {
            String query = " SELECT c.id, c.title, c.comment, ls.cost, ls.session_time, ls.session_start, ROUND(tgpa.summa,2), ls.to_number FROM contract AS c "
                  + " LEFT JOIN log_session_12_"+yyyyMM+" AS ls ON ls.cid = c.id"
                  + " LEFT JOIN " + TABLE_GROUPED_PHONE_ACCOUNT + " AS tgpa ON ls.cdr_id = tgpa.cdr_id AND ls.hour=tgpa.hour"
                  //+ " WHERE gr&("+ groupMask + ")>0 AND ls.session_time > 2 AND c.id IN (1758,1846) AND scid = -1 ORDER BY cdr_id";
                  + " WHERE gr&("+ groupMask + ")>0 AND ls.session_time > 2 AND scid = -1 ORDER BY c.id LIMIT 1000";
            sb.append(query);
         }

      int i = 0;


      PreparedStatement ps = con.prepareStatement(sb.toString());
      ResultSet rs = ps.executeQuery();
      while (rs.next())
         {
            Map<String, String> NewMap = new HashMap<String, String>();
Map<String, String>    NewMap2 = new HashMap<String, String>();
            //System.out.println("query " + sb.toString());
            j++;

            i++;
            //BigDecimal cost_oper = BigDecimal.ZERO;
            BigDecimal cost = BigDecimal.ZERO;
            BigDecimal cost_oper = BigDecimal.ZERO;
            int cid = rs.getInt(1);
            String title = rs.getString(2);
            String comment = rs.getString(3);
            cost = rs.getBigDecimal(4);
            time = time + rs.getInt(5);
            cost_oper = rs.getBigDecimal(7);
            String toNumber = rs.getString(8);
            int cdr_id = rs.getInt(9);
            NewMap.put( "cid", String.valueOf( cid ) );
            NewMap.put("title", title);
            NewMap.put("comment", comment);
            NewMap.put("count", cost.toString() );
            if ( cost_oper != null )
            {
            NewMap.put("count_oper", cost_oper.toString() );
            NewMap.put("time", rs.getString(6));
            NewMap.put("cost", cost.subtract(cost_oper).toString());
            NewMap.put("toNumber", toNumber);
            data.add(NewMap);
            allCost = allCost.add(cost.subtract(cost_oper));   
            allCount = allCount.add(cost);
            allCount_oper = allCount_oper.add(cost_oper);
            System.out.println("cdr_id " + cdr_id + " cdr_id_oper " + cdr_id);
            }
            //map.put("time", String.valueOf(rs.getInt(7)) + " время сессии " + rs.getString(8));
            //map.put("count", String.valueOf(j));
            /*if (cid != 588)
            {
            System.out.println("cdr_id " + cdr_id + " cdr_id_oper " + cdr_id);
            }
            
            String query = "SELECT cost, session_start FROM log_session_12_"+yyyyMM+" AS ls "
                  + "WHERE cid = 588 AND cdr_id = " + cdr_id;
            PreparedStatement psq = con.prepareStatement(query);
            ResultSet rsq = psq.executeQuery();
               while (rsq.next())
               {

                  cost_oper = rsq.getBigDecimal(1);
                  System.out.println("cost  " + rs.getBigDecimal(5).toString() + " cost_oper " + cost_oper + " cdr_id " + cdr_id + "\n\n");
                  NewMap.put("count", rs.getBigDecimal(5).toString() );
                  NewMap.put("count_oper", cost_oper.toString());
                  NewMap.put("time", rs.getString(8));
                  cost = rs.getBigDecimal(5).subtract(cost_oper);
               }
            */
            /*NewMap.put("cost", cost.toString());
            allCost = allCost.add(cost);   
            allCount = allCount.add(rs.getBigDecimal(5));
            allCount_oper = allCount_oper.add(cost_oper);
               */

            //NewMap2.put("count_oper", allCount_oper.toString());
            NewMap2.put("count", String.valueOf( 5 ));
            data.add(NewMap2);
            //data.add(NewMap);
         }
                     
      
      


      int Time = time/60;

      //map = new HashMap<String, String>();
      map.put("cost", allCost.toString());
      map.put("count", allCount.toString());
      map.put("count_oper", allCount_oper.toString());
      map.put("time", String.valueOf(Time) + " минут");
      //map.put("cost", allCost.toString());
      data.add(map);      
      result.setData(data);
   }

}

запрос выводит несколько договоров, по каждому ещё несколько полей, вот по каждому договору и хочу сделать подсчет

Страница 1 из 1 Часовой пояс: UTC + 5 часов [ Летнее время ]
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/