A 테이블에 (징계관련 테이블)
같은 mb_id 가 여러개 insert 가 가능한데요.
운영자가 회원을 징계하면 A테이블에 해당 내용이 쌓입니다.
이때 징계 횟수를 구분짓기 위해서
운영자가 a회원을 징계를 하면
1. A 테이블에 a회원의 징계 기록이 있는지 조회한다.
2. A 테이블에 a회원의 징계 기록이 있다면 insert 될 row에 stack 칼럼을 stack = stack +1 해준다.
이런 프로세스로 운영됩니다.
그래서
최초 A테이블의 자료를 보게되면
id = a | reason = 회원기만 | nick = gnu | stack = 1
id = a | reason = 광고홍보 | nick = gnu | stack = 2
이런 식으로 쌓이는데요.
이게 여러명이 될 경우에 검색에 조금 문제가 생겨버립니다.
id = a | reason = 회원기만 | nick = gnu | stack = 1
id = a | reason = 광고홍보 | nick = gnu | stack = 2
id = b | reason = 회원기만 | nick = kkk | stack = 1
id = b | reason = 광고홍보 | nick = kkk | stack = 2
id = b | reason = 광고홍보 | nick = kkk | stack = 3
만약 이렇게 쌓여있고
stack 이 2인 값을 검색 한다면
제가 원하는 값은
id = a | reason = 광고홍보 | nick = gnu | stack = 2
이렇게 하나만 나오게 하고 싶습니다..
근데 지금은
id = a | reason = 광고홍보 | nick = gnu | stack = 2
id = b | reason = 광고홍보 | nick = kkk | stack = 2
이렇게 b회원까지 나와버립니다.
b 회원은 stack이 3일때 나와야 하는데 말이죠;;
아래는 징계누적 페이지의 소스입니다.
<?php
$sub_menu = "860010";
include_once('./_common.php');
auth_check($auth[$sub_menu], 'w');
$g5['title'] = '징계';
include_once('./admin.head.php');
$colspan = 8;
$punish_table = 'g5_punish';
// 게시물 ////////////////////////////////////////////////////
$sop = strtolower($sop);
if ($sop != 'and' && $sop != 'or')
$sop = 'and';
$stx = trim($stx);
if ($sca || $stx) {
$sql_search = get_sql_admin_search($sca, $sfl, $stx, $sop);
// 가장 작은 번호를 얻어서 변수에 저장 (하단의 페이징에서 사용)
$sql = " select MIN(punish_no) as min_punish_id from {$punish_table} ";
$row = sql_fetch($sql);
$min_spt = (int)$row['min_punish_id'];
if (!$spt) $spt = $min_spt;
$sql_search .= " and (punish_no between {$spt} and ({$spt} + {$config['cf_search_part']})) ";
// 원글만 얻는다. (코멘트의 내용도 검색하기 위함)
// 라엘님 제안 코드로 대체 http://sir.kr/g5_bug/2922
// $sql = " SELECT COUNT(DISTINCT `wr_parent`) AS `cnt` FROM {$punish_table} WHERE {$sql_search} ";
$sql = " SELECT COUNT(*) AS `cnt` FROM {$punish_table} WHERE {$sql_search} ";
$row = sql_fetch($sql);
$total_count = $row['cnt'];
/*
$sql = " select distinct wr_parent from {$punish_table} where {$sql_search} ";
$result = sql_query($sql);
$total_count = sql_num_rows($result);
*/
} else {
$sql = " select count(distinct punish_id) as cnt from {$punish_table} where 1=1";
$row = sql_fetch($sql);
$sql_search = "";
$total_count = $row['cnt'];
}
$page_rows = 25;
$list_page_rows = 25;
if ($page < 1) { $page = 1; } // 페이지가 없으면 첫 페이지 (1 페이지)
// 년도 2자리
$today2 = G5_TIME_YMD;
$total_page = ceil($total_count / $page_rows); // 전체 페이지 계산
$from_record = ($page - 1) * $page_rows; // 시작 열을 구함
// 정렬에 사용하는 QUERY_STRING
$qstr2 = 'punish=punish_sum&sop='.$sop;
// 정렬
// 인덱스 필드가 아니면 정렬에 사용하지 않음
// if (!$sst || ($sst && !(strstr($sst, 'wr_id') || strstr($sst, "wr_datetime")))) {
// sst = 검색정렬필드
// sca = 카테고리
// sfl = 검색필드
// stx = 검색어
// sod = 검색오름, 내림차순
// sop = 검색 or, and 오퍼레이터
// spt = 검색 파트(구간)
if (!$sst) {
if ($board['bo_sort_field']) {
$sst = $board['bo_sort_field'];
} else {
$sst = " punish_no DESC"; // 징계횟수 많은순, 징계날짜 최신순
$sod = "";
}
} else {
// 게시물 리스트의 정렬 대상 필드가 아니라면 공백으로 (nasca 님 09.06.16)
// 리스트에서 다른 필드로 정렬을 하려면 아래의 코드에 해당 필드를 추가하세요.
// $sst = preg_match("/^(wr_subject|wr_datetime|wr_hit|wr_good|wr_nogood)$/i", $sst) ? $sst : "";
$sst = preg_match("/^(wr_datetime|wr_hit|wr_good|wr_nogood)$/i", $sst) ? $sst : "";
}
if(!$sst)
$sst = " punish_no DESC"; // 신고횟수
if ($sst) {
$sql_order = "ORDER BY {$sst} {$sod}";
// $sql_order = " GROUP BY punish_id ORDER BY {$sst} {$sod} "; 2018-05-03 누적징계횟수 group by
}
if ($sca || $stx) {
if ($sfl == "punish_stack") {
$sql_where_stack = " "; // 이부분에 where 절을 써서 구분지을수 있을지!?
}
$sql = " SELECT * FROM {$punish_table} WHERE {$sql_search} {$sql_where_stack} {$sql_order} limit {$from_record}, $page_rows";
} else {
/* 2018-05-03 누적징계횟수 group by */
$sql = " SELECT tt.*
FROM {$punish_table} tt
INNER JOIN
(SELECT punish_id, max(punish_stack) AS maxPunishStack
FROM {$punish_table}
GROUP BY punish_id) groupedtt
ON tt.punish_id = groupedtt.punish_id
AND tt.punish_stack = groupedtt.maxPunishStack
{$sql_order}
LIMIT {$from_record}, $page_rows
";
}
echo $sql;
if ($page_rows > 0) {
$result = sql_query($sql);
$i = 0;
$k = 0;
$list = array();
while ($row = sql_fetch_array($result)) {
$punish_list = array_push($list, $row);
$list_num = $total_count - ($page - 1) * $list_page_rows;
$list[$i]['num'] = $list_num - $k;
$delete_href ='./punish_delete.php?punish_no='.$row['punish_no'].'&token='.$token.'&page='.$page; // 2018-04-27 .urldecode($qstr) 삭제함.
$list[$i]['delete_href'] = $delete_href;
$i++;
$k++;
}
}
$write_pages = get_paging(25, $page, $total_page, $_SERVER['SCRIPT_NAME'] . '?' . $qstr . '&page=');
////////////////////////////////////////////////////
?>
<form name="fboardlist" id="fboardlist" action="./board_list_update.php" onsubmit="return fboardlist_submit(this);" method="post">
<input type="hidden" name="bo_table" value="<?php echo $bo_table ?>">
<input type="hidden" name="sfl" value="<?php echo $sfl ?>">
<input type="hidden" name="stx" value="<?php echo $stx ?>">
<input type="hidden" name="spt" value="<?php echo $spt ?>">
<input type="hidden" name="sca" value="<?php echo $sca ?>">
<input type="hidden" name="sst" value="<?php echo $sst ?>">
<input type="hidden" name="sod" value="<?php echo $sod ?>">
<input type="hidden" name="page" value="<?php echo $page ?>">
<input type="hidden" name="sw" value="">
<div class="tbl_head01 tbl_wrap total_punish_wrap">
<table>
<caption>누적 신고</caption>
<thead>
<tr>
<th scope="col" class="td_num">번호</th>
<th scope="col" class="td_id">아이디</th>
<th scope="col" class="td_nick">닉네임</th>
<th scope="col" class="td_kind">징계종류</th>
<th scope="col" class="td_memo">징계내용</th>
<th scope="col" class="td_datetime">징계기간(일자)</th>
<th scope="col" class="td_stack">누적징계횟수</th>
<th scope="col" class="td_note">메모</th>
<th scope="col" class="td_check">삭제</th>
</tr>
</thead>
<tbody>
<?php
$today = date("Y-m-d");
for ($i = 0; $i<count($list); $i++) {
$bg = 'bg' . ($i % 2);
?>
<tr class="<?php echo $bg; ?>">
<td scope="row" class="td_num">
<?php echo $list[$i]['num']; ?>
</td>
<td scope="row" class="td_id">
<?php echo $list[$i]['punish_id']; ?>
</td>
<td scope="row" class="td_nick">
<?php echo $list[$i]['punish_nick']; ?>
</td>
<td scope="row" class="td_kind">
<?php echo $list[$i]['punish_kind']; ?>
</td>
<td scope="row" class="td_memo">
<?php echo $list[$i]['punish_memo']; ?>
</td>
<td scope="row" class="td_datetime">
<?php
$year = date("Y"); // 이번년도
$start_year = substr($list[$i]['punish_start_datetime'],0,4); // 징계시작 년도만 ex) 2018
$end_year = substr($list[$i]['punish_end_datetime'],0,4); // 징계끝 년도만 ex) 2018
$punish_start_year_time = substr($list[$i]['punish_start_datetime'],2,9); // 2018.xx.xx로 변환
$punish_end_year_time = substr($list[$i]['punish_end_datetime'],2,9); // 2018.xx.xx로 변환
$punish_start_time = substr($list[$i]['punish_start_datetime'],5,5); // xx.xx (월일만)
$punish_end_time = substr($list[$i]['punish_end_datetime'],5,5); // xx.xx (월일만)
if ($list[$i]['punish_kind'] == "경고" && $year == $start_year && $year == $end_year) { // 경고이고 징계시작과 끝이 같은 년도라면
$punish_datetime = $punish_start_year_time."~".$punish_end_time;
} else {
$punish_datetime = $punish_start_year_time;
}
?>
<?php echo $punish_datetime; ?>
</td>
<td scope="row" class="td_stack">
<?php echo $list[$i]['punish_stack']; ?>
</td>
<td scope="row" class="td_note">
<?php echo $list[$i]['punish_note']; ?>
</td>
<td scope="row" class="td_check">
<!--
<input type="checkbox" value="<?php echo $list[$i]['punish_no'] ?>" name="chk_punish_<?php echo $list[$i]['punish_no'] ?>" id="chk_punish_<?php echo $list[$i]['punish_no'] ?>">
-->
<a href="<?php echo $list[$i]['delete_href'] ?>" onclick="del(this.href); return false;" id="btnDelete">삭제</a>
</td>
</tr>
<?php } ?>
<?php if($i == 0 ) { ?><tr><td colspan="8" style="text-align: center; line-height:50px">자료가 없습니다.</td></tr><?php } ?>
</tbody>
</table>
</div>
</form>
<?php echo $write_pages; ?>
<div class="btn_wrap">
<?php if ($stx) {?>
<a href="./punish_sum.php" target="_self" id="btnList">목록</a>
<?php } ?>
</div>
<fieldset class="punish_sum_search">
<form name="fsearch" id="fsearch" method="get">
<label for="sfl" class="sound_only">검색대상</label>
<select name="sfl" id="sfl">
<option value="punish_id"<?php echo get_selected($sfl, "punish_id"); ?>>회원아이디</option>
<option value="punish_nick"<?php echo get_selected($sfl, "punish_nick"); ?>>닉네임</option>
<option value="punish_kind"<?php echo get_selected($sfl, "punish_kind"); ?>>종류</option>
<option value="punish_memo"<?php echo get_selected($sfl, "punish_memo"); ?>>내용</option>
<option value="punish_start_datetime || punish_end_datetime"<?php echo get_selected($sfl, "punish_start_datetime || punish_end_datetime"); ?>>일자</option>
<option value="punish_stack"<?php echo get_selected($sfl, "punish_stack"); ?>>징계횟수</option>
</select>
<label for="stx" class="sound_only">검색어<strong class="sound_only"> 필수</strong></label>
<input type="text" name="stx" value="<?php echo $stx ?>" id="stx" required class="required frm_input">
<input type="submit" value="검색" class="btn_submit">
</form>
</fieldset>
<style>
.total_punish_wrap td{text-align: center}
.td_num{width: 50px}
.td_id{width: 120px}
.td_kind{width: 200px}
.td_nick{width: 120px}
.td_memo{width: 120px}
.td_datetime{width: 200px}
.td_stack{width: 60px}
.td_check{width: 60px}
.punish_sum_search {
margin: 0 0 10px;
padding: 0 20px;
text-align: center;
}
.punish_sum_search select,
.punish_sum_search .frm_input,
.punish_sum_search .btn_submit{
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
height: 30px;
line-height: 30px;
}
.punish_sum_search .btn_submit{
width: 80px;
}
#btnList{
display: inline-block;
width: 50px;
height: 30px;
line-height: 30px;
text-align: center;
background: #e2e2e2;
}
.btn_wrap{
margin: 0 0 10px;
padding: 0 20px;
text-align: right;
}
</style>
<?php
include_once('./admin.tail.php');
?>
답변 3개 / 댓글 4개
검색 조건이 확실하지가 않네요
stack = 2 인 사람을 검색한다면 2개가 나오는게 맞습니다.
검색 조건이 회원의 마지막 징계리스트를 구하는 것이라면
select b.* from
(select mb_id, max(stack) as stack from A_table group by mb_id) as a
left join A_table as b on a.mb_id = b.mb_id and a.stack = b.stack
이정도 되지 않을까요??? 에러나려나???
테이블자료가 없서서 실행해 보지는 못하네요ㅠㅠ
이것은 2가 마지막인 사람
select b.* from
(select mb_id, max(stack) as stack from A_table group by mb_id having stack = '2') as a
left join A_table as b on a.mb_id = b.mb_id and a.stack = b.stack
이럴땐 해당 테이블내에서 중복갯수를 구하는 쿼리를 이용하시면됩니다
select *,count(*) from 테이블명 group by id having count(*)=검색숫자
group by로 중복되는 id값들을 묶어주고 해당 id에 대한 테이블에서 스택갯수를 구합니다
그럼 count(*)에 몇번 신고가되었는지 집계가 될것이고 count(*)를 통해서 검색시 숫자를 집어넣어 카운트가 2개인것만 찾으면 되는겁니다
라고 생각하긴했는데
스택이 초기화될 경우도 있겠다 싶어 (기록은남고)
select * from 테이블명 where stack=검색시숫자 group by id
이런식으로 하시면 가장 최근 값만 남기고 합쳐지니 될것같습니다
초기화되는 경우가 아니면 위쪽이 좀더 정확하겠네요
답변에 대한 댓글 1개
답변을 작성하려면 로그인이 필요합니다.
테이블 이렇게 생겼습니다
SELECT b.* FROM
(SELECT punish_id, max(punish_stack) AS stack
FROM g5_punish
GROUP BY punish_id
HAVING punish_stack = '2') AS a
LEFT JOIN g5_punish AS b on a.punish_id = b.punish_id AND a.stack = b.stack
[/code]
having 절이 에러가 나는 이유가 뭘까요;;